java ProcessBuilder运行的shell脚本已挂起

lou*_*Hou 5 java

我正在尝试使用ProcessBuilder运行Shell脚本。该脚本可以运行,但是不能在Java代码之后运行。错误流不会输出消息。我正在centOS 6.9计算机上运行它。请在下面找到我的代码。

public static ArrayList<String> runCommand(ArrayList<String> command)throws IOException {

        ProcessBuilder processBuilder = new ProcessBuilder();
        processBuilder.command(command);
        Process process = processBuilder.start();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

        ArrayList<String> commandOutput = new ArrayList<>();
        String str;
        while((str = reader.readLine()) != null) {
            commandOutput.add(str);
        }

        StringBuilder errorBuilder = new StringBuilder();
        while((str = errorReader.readLine()) != null) {
            errorBuilder.append(str);
        }

        String errorMessage = errorBuilder.toString();
        if(!errorMessage.equals("")) {
            String message = LOG_TAG + ",[runCommand] error:" + errorMessage;
            System.out.println(message);
        }

        reader.close();
        errorReader.close();
        process.destroy();

        return commandOutput;
    }
Run Code Online (Sandbox Code Playgroud)

Kar*_*bak 1

In your case, you are reading something from the output stream of the process, till you consume everything. Then, you try to read error stream.

If the process writes some considerable number of characters on the error stream, the other process will block till they are consumed. To consume both error stream and output stream at the same time, you need to use threads.

您可以遵循该StreamGobbler技术。您可以从该页面获得一些详细信息:https://www.javaworld.com/article/2071275/when-runtime-exec---won-t.html ?page=2

这是受页面影响的一些代码:

public class StreamGobbler extends Thread {
    private static final String EOL = System.lineSeparator();
    private final InputStream inputStream;
    private final StringBuilder output = new StringBuilder();

    public StreamGobbler(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    public void run() {
        try (InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
             BufferedReader reader = new BufferedReader(inputStreamReader);
        ) {
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line);
                output.append(EOL);
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    public String getOutput() {
        return output.toString();
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的代码中,您可以StreamGobbler这样使用:

    StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream());
    StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream());

    process.waitFor();

    String commandOutput = outputGobbler.getOutput();
    String errorMessage = errorGobbler.getOutput();
    process.destroy();
Run Code Online (Sandbox Code Playgroud)