java ProcessBuilder运行shell脚本挂起

java ProcessBuilder运行shell脚本挂起,java,Java,我正在尝试使用ProcessBuilder运行shell脚本。该脚本可以工作,但无法在java代码之后运行。错误流不输出消息。我在centOS 6.9计算机上运行它。请在下面找到我的代码 public static ArrayList<String> runCommand(ArrayList<String> command)throws IOException { ProcessBuilder processBuilder = new ProcessBu

我正在尝试使用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;
    }
公共静态ArrayList运行命令(ArrayList命令)引发IOException{
ProcessBuilder ProcessBuilder=新的ProcessBuilder();
processBuilder.command(command);
Process=processBuilder.start();
BufferedReader=新的BufferedReader(新的InputStreamReader(process.getInputStream());
BufferedReader errorReader=新的BufferedReader(新的InputStreamReader(process.getErrorStream());
ArrayList commandOutput=新的ArrayList();
字符串str;
而((str=reader.readLine())!=null){
commandOutput.add(str);
}
StringBuilder errorBuilder=新建StringBuilder();
而((str=errorReader.readLine())!=null){
errorBuilder.append(str);
}
字符串errorMessage=errorBuilder.toString();
如果(!errorMessage.equals(“”){
String message=LOG_TAG+”,[runCommand]错误:“+errorMessage;
System.out.println(消息);
}
reader.close();
errorReader.close();
process.destroy();
返回命令输出;
}

在您的情况下,您正在从流程的输出流中读取某些内容,直到您消耗掉所有内容。然后,尝试读取错误流

如果进程在错误流中写入了相当数量的字符,那么另一个进程将阻塞,直到它们被使用为止。要同时使用错误流和输出流,需要使用线程

您可以遵循
StreamGobbler
技术。您可以从该页面获得一些详细信息:

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

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();
    }
}
在您的代码中,您可以这样使用
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();

尝试在线程中使用输出流(或通过stdout重定向错误并使用单个线程),并在
进程上使用
waitFor
等待它完成执行