Java Runtime.getRuntime (): कमांड लाइन प्रोग्राम निष्पादित करने से आउटपुट मिलता है


155

मैं अपने जावा प्रोग्राम से कमांड प्रॉम्प्ट कमांड चलाने के लिए रनटाइम का उपयोग कर रहा हूं। हालाँकि, मुझे इस बात की जानकारी नहीं है कि मैं आउटपुट कैसे प्राप्त कर सकता हूँ।

यहाँ मेरा कोड है:

Runtime rt = Runtime.getRuntime();

String[] commands = {"system.exe", "-send" , argument};

Process proc = rt.exec(commands);

मैंने करने की कोशिश की System.out.println(proc);लेकिन वह कुछ भी वापस नहीं आया। उस कमांड के निष्पादन को अर्धविराम द्वारा अलग किए गए दो नंबरों को वापस करना चाहिए। मैं इसे प्रिंट करने के लिए एक चर में कैसे प्राप्त कर सकता हूं?

यहाँ अब मैं उपयोग कर रहा है कोड है:

String[] commands = {"system.exe", "-get t"};

Process proc = rt.exec(commands);

InputStream stdIn = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdIn);
BufferedReader br = new BufferedReader(isr);

String line = null;
System.out.println("<OUTPUT>");

while ((line = br.readLine()) != null)
     System.out.println(line);

System.out.println("</OUTPUT>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);

लेकिन मुझे अपने आउटपुट के रूप में कुछ भी नहीं मिल रहा है, लेकिन जब मैं उस कमांड को खुद चलाता हूं तो यह ठीक काम करता है।

जवाबों:


244

यहाँ जाने का तरीका है:

Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-get t"};
Process proc = rt.exec(commands);

BufferedReader stdInput = new BufferedReader(new 
     InputStreamReader(proc.getInputStream()));

BufferedReader stdError = new BufferedReader(new 
     InputStreamReader(proc.getErrorStream()));

// Read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
    System.out.println(s);
}

// Read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
    System.out.println(s);
}

अधिक जानकारी के लिए यहां जावदोक पढ़ें । ProcessBuilderउपयोग करने के लिए एक अच्छा विकल्प होगा।


4
@AlbertChen pwd && lsकेवल एक फ़ाइल निष्पादित नहीं कर रहा है, जब आप ऐसा करते हैं कि शेल में यह निष्पादन /bin/pwdऔर /bin/lsनिष्पादन दोनों को निष्पादित करता है । यदि आप इस तरह का सामान करना चाहते हैं तो जावा में आपको कुछ ऐसा करने की आवश्यकता होगी {"/bin/bash","-c", "pwd && ls"}। आपके पास शायद अब सवाल नहीं है, लेकिन अन्य लोग शायद इसलिए मुझे लगा कि मैं इसका जवाब दे सकता हूं।
735Tesla

3
मुझे लगता है कि दो धाराओं को पढ़ना समवर्ती रूप से हो रहा होगा क्योंकि अगर, आपके मामले की तरह, stdStream का आउटपुट बफर को भर देगा, तो आप त्रुटि स्ट्रीम को पढ़ने में सक्षम नहीं होंगे ..
Li3ro

3
Li3ro आंशिक रूप से सही है। जिस प्रोग्राम को आप सुन रहे हैं, उसके लिए एक सीमित बफर stdoutऔर stderrआउटपुट है। यदि आप उन्हें समवर्ती रूप से नहीं सुनते हैं, तो उनमें से एक आपको पढ़ते समय भर जाएगा। आप जिस प्रोग्राम को सुन रहे हैं, उसे भरे हुए बफ़र पर लिखने की कोशिश करना बंद कर देंगे, जबकि दूसरे छोर पर आपका प्रोग्राम एक ऐसे बफ़र से पढ़ने की कोशिश करेगा, जो कभी वापस नहीं आएगा EOF। आपको दोनों धाराओं को समवर्ती रूप से पढ़ना चाहिए
जिली

1
@ गिल्ली तो Li3ro "आंशिक रूप से" सही क्यों है? क्या Li3ro सिर्फ पूरी तरह से और पूरी तरह से सही नहीं है? इस मामले में, मुझे समझ नहीं आ रहा है कि 2011 के बाद से एक गलत जवाब क्यों इधर-उधर लटका हुआ है और यह 200 से अधिक अपवित्र क्यों है ... यह भ्रामक है।
एंड्री टाइयुकिन सेप

2
@AndreyTyukin आप सही हैं। सभी मौजूदा जवाब गतिरोध के लिए कमजोर हैं। मैं उन्हें दृश्यता हासिल करने के लिए अन्य जवाब देने की अनुमति देने के लिए उन्हें प्रोत्साहित करने के लिए प्रोत्साहित करता हूं। मैंने आपकी समीक्षा के लिए एक नया उत्तर पोस्ट किया: stackoverflow.com/a/57949752/14731 । उम्मीद है कि मुझे यह अधिकार मिल गया ...
गिली

68

एक तेज़ तरीका यह है:

public static String execCmd(String cmd) throws java.io.IOException {
    java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}

जो मूल रूप से इसका एक संक्षिप्त संस्करण है:

public static String execCmd(String cmd) throws java.io.IOException {
    Process proc = Runtime.getRuntime().exec(cmd);
    java.io.InputStream is = proc.getInputStream();
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    String val = "";
    if (s.hasNext()) {
        val = s.next();
    }
    else {
        val = "";
    }
    return val;
}

मुझे पता है कि यह प्रश्न पुराना है, लेकिन मैं इस उत्तर को पोस्ट कर रहा हूं क्योंकि मुझे लगता है कि यह जल्दी हो सकता है।


4
अच्छे उत्तर के लिए धन्यवाद। "\\ A" सीमांकक क्यों है?
गोटफ्रीड

1
मुझे पूरी तरह से याद नहीं है कि जब मैंने मूल रूप से यह लिखा था तब मेरा तर्क क्या था। मैं थोड़ी देर के लिए इस समाधान का उपयोग कर रहा हूं, लेकिन मुझे लगता है कि ऐसा इसलिए था क्योंकि \Aरेगेक्स का मतलब स्ट्रिंग की शुरुआत है और मुझे स्लैश से बचना था।
735Tesla

5
"\ A" घंटी का पात्र है। "^" regex में एक स्ट्रिंग की शुरुआत है, और "$" regex में एक स्ट्रिंग का अंत है। यह एक ऐसा चरित्र है, जिसे आप नहीं देखना चाहेंगे। जावा दस्तावेज़ के अनुसार डिफ़ॉल्ट सीमांकक व्हॉट्सएप है, इसलिए ऐसा करने से संभवतः कमांड का पूरा परिणाम निकल जाएगा।
हंक शुल्त्

11

ProcessBuilderसुझाए गए सेंथिल के रूप में उपयोग करने के अलावा , जब Runtime.exec () नहीं होगा की सभी सिफारिशों को पढ़ना और लागू करना सुनिश्चित करें ।


यह स्निपेट मानक त्रुटि स्ट्रीम (जैसा कि लिंक किए गए लेख में अनुशंसित है) का उपभोग नहीं करता है। यह भी ProcessBuilderदो बार की सिफारिश के रूप में उपयोग नहीं कर रहा है । ए का उपयोग करते हुए ProcessBuilder, आउटपुट और त्रुटि धाराओं को मर्ज करना संभव है, ताकि एक ही बार में दोनों का उपभोग करना आसान हो सके।
एंड्रयू थॉम्पसन

11

यदि उपयोग पहले से ही Apache commons-io है जो क्लासपाथ पर उपलब्ध है, तो आप उपयोग कर सकते हैं:

Process p = new ProcessBuilder("cat", "/etc/something").start();
String stderr = IOUtils.toString(p.getErrorStream(), Charset.defaultCharset());
String stdout = IOUtils.toString(p.getInputStream(), Charset.defaultCharset());

7

इसके अलावा हम कमांड आउटपुट प्राप्त करने के लिए धाराओं का उपयोग कर सकते हैं:

public static void main(String[] args) throws IOException {

        Runtime runtime = Runtime.getRuntime();
        String[] commands  = {"free", "-h"};
        Process process = runtime.exec(commands);

        BufferedReader lineReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        lineReader.lines().forEach(System.out::println);

        BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
        errorReader.lines().forEach(System.out::println);
    }

7

@Senthil और @Arend जवाब ( https://stackoverflow.com/a/5711150/2268559 ) का उल्लेख किया ProcessBuilder। यहाँ ProcessBuilderकमांड के लिए पर्यावरण चर और कार्यशील फोल्डर निर्दिष्ट करने के साथ उदाहरण दिया गया है:

    ProcessBuilder pb = new ProcessBuilder("ls", "-a", "-l");

    Map<String, String> env = pb.environment();
    // If you want clean environment, call env.clear() first
    //env.clear();
    env.put("VAR1", "myValue");
    env.remove("OTHERVAR");
    env.put("VAR2", env.get("VAR1") + "suffix");

    File workingFolder = new File("/home/user");
    pb.directory(workingFolder);

    Process proc = pb.start();

    BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));

    BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

    // Read the output from the command:
    System.out.println("Here is the standard output of the command:\n");
    String s = null;
    while ((s = stdInput.readLine()) != null)
        System.out.println(s);

    // Read any errors from the attempted command:
    System.out.println("Here is the standard error of the command (if any):\n");
    while ((s = stdError.readLine()) != null)
        System.out.println(s);

6

इस लेखन के समय, कोड सहित अन्य सभी उत्तरों में गतिरोध उत्पन्न हो सकता है।

प्रक्रियाओं में उत्पादन stdoutऔर stderrउत्पादन के लिए एक सीमित बफर होता है। यदि आप उन्हें समवर्ती रूप से नहीं सुनते हैं, तो उनमें से एक भर जाएगा जबकि आप दूसरे को पढ़ने की कोशिश कर रहे हैं। उदाहरण के लिए, आप पढ़ने के लिए प्रतीक्षा कर सकते हैं stdoutजबकि प्रक्रिया लिखने के लिए इंतजार कर रही है stderr। आप stdoutबफर से नहीं पढ़ सकते क्योंकि यह खाली है और प्रक्रिया stderrबफर को नहीं लिख सकती क्योंकि यह भरा हुआ है। आप एक-दूसरे के हमेशा के लिए इंतजार कर रहे हैं।

गतिरोध के जोखिम के बिना प्रक्रिया के आउटपुट को पढ़ने का एक संभावित तरीका यहां दिया गया है:

public final class Processes
{
    private static final String NEWLINE = System.getProperty("line.separator");

    /**
     * @param command the command to run
     * @return the output of the command
     * @throws IOException if an I/O error occurs
     */
    public static String run(String... command) throws IOException
    {
        ProcessBuilder pb = new ProcessBuilder(command).redirectErrorStream(true);
        Process process = pb.start();
        StringBuilder result = new StringBuilder(80);
        try (BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())))
        {
            while (true)
            {
                String line = in.readLine();
                if (line == null)
                    break;
                result.append(line).append(NEWLINE);
            }
        }
        return result.toString();
    }

    /**
     * Prevent construction.
     */
    private Processes()
    {
    }
}

कुंजी का उपयोग करना है ProcessBuilder.redirectErrorStream(true)जो धारा stderrमें पुनर्निर्देशित करेगा stdout। यह आपको एक ही स्ट्रीम को पढ़ने की अनुमति देता है, जिसके बीच में वैकल्पिक करने के लिए stdoutऔर stderr। यदि आप इसे मैन्युअल रूप से लागू करना चाहते हैं, तो आपको दो अलग-अलग थ्रेड्स में स्ट्रीम का उपभोग करना होगा ताकि आप कभी भी ब्लॉक न कर सकें।


ओह वाह! मुझे उम्मीद नहीं थी कि आप टिप्पणी पर इतनी जल्दी जवाब देंगे, अकेले ही इस पुराने प्रश्न का उत्तर दें! :) मैं अब एक इनाम शुरू करने पर विचार कर रहा हूं। बाद में आपके उत्तर पर एक नज़र डालेंगे। धन्यवाद!
एंड्री टायुकिन

1

यदि आप कोटलिन पर लिखते हैं, तो आप उपयोग कर सकते हैं:

val firstProcess = ProcessBuilder("echo","hello world").start()
val firstError = firstProcess.errorStream.readBytes().decodeToString()
val firstResult = firstProcess.inputStream.readBytes().decodeToString()

0

पिछले उत्तर से अनुकूलित:

public static String execCmdSync(String cmd, CmdExecResult callback) throws java.io.IOException, InterruptedException {
    RLog.i(TAG, "Running command:", cmd);

    Runtime rt = Runtime.getRuntime();
    Process proc = rt.exec(cmd);

    //String[] commands = {"system.exe", "-get t"};

    BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
    BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

    StringBuffer stdOut = new StringBuffer();
    StringBuffer errOut = new StringBuffer();

    // Read the output from the command:
    System.out.println("Here is the standard output of the command:\n");
    String s = null;
    while ((s = stdInput.readLine()) != null) {
        System.out.println(s);
        stdOut.append(s);
    }

    // Read any errors from the attempted command:
    System.out.println("Here is the standard error of the command (if any):\n");
    while ((s = stdError.readLine()) != null) {
        System.out.println(s);
        errOut.append(s);
    }

    if (callback == null) {
        return stdInput.toString();
    }

    int exitVal = proc.waitFor();
    callback.onComplete(exitVal == 0, exitVal, errOut.toString(), stdOut.toString(), cmd);

    return stdInput.toString();
}

public interface CmdExecResult{
    void onComplete(boolean success, int exitVal, String error, String output, String originalCmd);
}

0

इस पृष्ठ पर अन्य स्निपेट की तरह ही बहुत सुंदर है लेकिन सिर्फ एक समारोह में चीजों को व्यवस्थित करना , यहां हम जाते हैं ...

String str=shell_exec("ls -l");

कक्षा समारोह:

public String shell_exec(String cmd)
       {
       String o=null;
       try
         {
         Process p=Runtime.getRuntime().exec(cmd);
         BufferedReader b=new BufferedReader(new InputStreamReader(p.getInputStream()));
         String r;
         while((r=b.readLine())!=null)o+=r;
         }catch(Exception e){o="error";}
       return o;
       }

-1

InputStreamरनटाइम पढ़ने की कोशिश करें :

Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-send", argument};
Process proc = rt.exec(commands);
BufferedReader br = new BufferedReader(
    new InputStreamReader(proc.getInputStream()));
String line;
while ((line = br.readLine()) != null)
    System.out.println(line);

यदि आप proc.getErrorStream()प्रक्रिया त्रुटि आउटपुट को प्रिंट कर रहे हैं, तो आपको त्रुटि स्ट्रीम ( ) को भी पढ़ना पड़ सकता है । यदि आप उपयोग करते हैं तो आप त्रुटि स्ट्रीम को इनपुट स्ट्रीम पर पुनर्निर्देशित कर सकते हैं ProcessBuilder

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.