Runtime.getRuntime (). Exec ("C: \ cygwin \ bin \ bash.exe") hat keine Eingabe zum Lesen von

Ich versuche, einen neuen Prozess auszuführen und aus seinem Eingabestream in Java zu lesen. Ich habe Runtime.getRuntime (). Exec (String) erfolgreich zum Starten und Empfangen von Eingaben von mehreren Prozessen verwendet. Wenn ich jedoch versuche, exec für einige andere Prozesse zu verwenden, wird die Lesemethode des Eingabestreams blockiert, und es scheint, dass keine Eingabe vorliegt. Was kann dazu führen, dass der Eingabestream für einige dieser Prozesse leer ist? Insbesondere frage ich mich, warum bash.exe nichts ausgibt.

Ich habe einen JUnit-Testfall geschrieben, um dieses Problem zu demonstrieren:

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import junit.framework.TestCase;

public class TestExec extends TestCase {

    public void testExec() throws IOException {
        List<InputPrinter> threads = new ArrayList<InputPrinter>();

        // Create a process for each of the commands and make sure that
        // it outputs at least one line to its input stream.
        threads.add(testExec("cmd"));
        threads.add(testExec("java"));
        threads.add(testExec("C:/cygwin/bin/vim-nox.exe"));

        // These bottom two fail, even though executing these
        // commands in cmd.exe results in immediate output
        threads.add(testExec("javac"));
        threads.add(testExec("C:/cygwin/bin/bash.exe"));

        // Give the threads a second to execute
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
            fail();
        }

        // Test that each command had input to read
        for(InputPrinter ip : threads) {
            assertTrue(ip.command + " has not read any input", ip.hasRead);
        }
    }

    // Starts a process for the given command and returns an
    // InputPrinter that can be used to check if the process
    // has had an input to read.
    public InputPrinter testExec(String command) throws IOException {
        Process proc = Runtime.getRuntime().exec(command);
        InputStream in = proc.getInputStream();

        InputPrinter ip = new InputPrinter(in, command);
        new Thread(ip).start();

        return ip;
    }

    // Simple Runnable to read from an InputStream. hasRead will be
    // true if at least one input has been read from the stream
    private class InputPrinter implements Runnable {
        InputStream in;
        String command;
        boolean hasRead;

        public InputPrinter(InputStream in, String command) {
            this.in = in;
            this.command = command;
            this.hasRead = false;
        }

        // Loop indefinitely while printing any received input
        public void run() {
            try {
                final byte[] b = new byte[1024];
                while (true) {
                    int n = in.read(b);
                    if (n > 0) {
                        System.out.print(new String(Arrays.copyOf(b, n)));
                        hasRead = true;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                fail();
            }
        }
    }

}

BEARBEITEN

Soweit ich weiß, sollte in der Windows-Eingabeaufforderung nichts angezeigt werden, wenn ein Programm weder stdout noch stderr verwendet. Was ich beim Starten des Bash-Prozesses erwarte, ist "bash-3.2 !$3$!quot;. Dasselbe sehe ich, wenn ich die Eingabeaufforderung öffne und "bash.exe" ausführe:

Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\cygwin\bin>bash.exe
bash-3.2$

Antworten auf die Frage(4)

Ihre Antwort auf die Frage