在 Java 中,我正在啟動一個子行程,如下所示:
String[] command = {"java", "-jar", jarPath};
Process childProcess = new ProcessBuilder().inheritIO().command(command).start();
我希望子行程Success!在某個時候列印到標準輸出(如果事情成功的話)。我如何定期(例如,每 5 秒)檢查Success!輸出中是否有由子行程創建的行?
uj5u.com熱心網友回復:
如果要使用子行程執行 IO,請不要使用inheritIO. 相反,通過以下方式捕獲行程的輸出流getInputStream()并通過以下方式讀取它BufferedReader:
final Process childProcess = new ProcessBuilder().command(command).start();
try (final BufferedReader br = new BufferedReader(new InputStreamReader(childProcess.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) {
if (line.equals("Success!")) {
System.out.println("Successfully completed");
// Maybe, depending on whether you need the remaining output:
break;
} else {
// Handle output from process; e.g.:
System.out.println("No success yet.");
}
}
}
// At this point, the child process has not yet necessarily completed!
childProcess.waitFor();
重要的是,您不需要定期檢查輸出:回圈執行同步 IO,即它會自動等待,直到有來自子行程的輸出可用。您需要做的就是檢查輸出是否符合您的預期。
uj5u.com熱心網友回復:
所以......這是一個相當復雜的問題,盡管僅僅問它可能并不明顯。
我無法使用ProcessBuilder課程來做到這一點
(也許有更多經驗的人可以使用該路線回答)。
這是您需要做的:使用該類Runtime.getRuntime().exec(command)來運行您的命令。這使您可以輕松訪問標準輸入和標準錯誤流。
以下是您可以使用的通用完整類。
用法:
final String jarPath = "jarPath.jar";
final String[] command = { "java.exe", "-jar", jarPath };
final CrossPlatformCommand childProcess = new CrossPlatformCommand();
final int exitCode = childProcess.execute(command[0] " " command[1] " " command[2]);
System.out.println("Parse child process output: " childProcess.getInput());
輸出:
Parse child process output: Success!
對此有一些警告:在 Linux 中需要對美元符號進行轉義。可能還有其他字符需要轉義(這個還沒有完全調查清楚,如果你使用了其他需要轉義的字符,你可能需要修改這個類。)
public class CrossPlatformCommand
{
private static final String SHELL_LINUX = "/bin/bash";
private static final int BUFFER_SIZE = 4096;
private static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.getDefault());
private final StringBuffer error = new StringBuffer();
private final StringBuffer input = new StringBuffer();
public int execute(final String command) throws Exception
{
final int exitCode;
if (OS_NAME.startsWith("windows"))
{
exitCode = executeWindows(command);
}
else
{
exitCode = executeLinux(command); // OS_NAME.startsWith("linux")
}
return exitCode;
}
public String getError()
{
return this.error.toString();
}
public String getInput()
{
return this.input.toString();
}
private int executeLinux(final String command) throws Exception
{
final Process proc = Runtime.getRuntime().exec(SHELL_LINUX);
processLinuxCommand(proc, command);
return processStreams(proc);
}
private int executeWindows(final String command) throws Exception
{
final Process proc = Runtime.getRuntime().exec(command);
return processStreams(proc);
}
private static void processLinuxCommand(final Process proc, final String command) throws Exception
{
try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())))
{
// Dollar signs are special in Linux.
out.write(command.replace("$", "\\$"));
out.newLine();
out.flush();
}
}
private int processStreams(final Process proc) throws Exception
{
fillBuffer(proc.getInputStream(), this.input);
fillBuffer(proc.getErrorStream(), this.error);
return proc.waitFor();
}
private static void fillBuffer(final InputStream in, final StringBuffer sb) throws IOException
{
sb.setLength(0);
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
final char[] buffer = new char[BUFFER_SIZE];
final int length = reader.read(buffer);
for (int i = 0; i < length; i )
{
sb.append(buffer[i]);
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/361158.html
上一篇:在JMeter執行緒組中共享變數
