大家好,我是Java新手。
我目前正在构建一个Java应用程序,使用Java Process builder执行多个linux命令。
我计划执行一个shell脚本,由于这个shell脚本是一个外部程序,需要大约一秒钟才能完全执行,所以让进程休眠一秒钟,并将结果写入一个txt文件。
这是一个外部程序,它必须接收"要退出程序,所以我最后需要在终端中输入q。
我以前在这个社区得到过帮助,我用这些帮助构造的代码如下。
public static void Linux(String fileName){
try {
File dir = new File("/usr/local/bin");
ProcessBuilder pb = new ProcessBuilder(new String[]{"/bin/bash", "-c", "./test_elanprv2.2.sh > "$1"; sleep 1; q", "_", fileName + ".txt"});
System.out.println("wrote text");
pb.directory(dir);
Process start = pb.start();
start.destroy();
}catch (Exception e){
e.printStackTrace();
System.out.println("failed to write text");
}
进程构建器确实创建了一个txt文件,但它似乎是空的,并且无论我将睡眠设置为多长时间,程序似乎都会立即返回打印语句。
如果有人能告诉我我做错了什么,我将不胜感激。提前感谢!!
正如@VGR所提到的,尝试使用redirectOutput
public static void Linux(String fileName){
try {
File dir = new File("/usr/local/bin");
ProcessBuilder pb = new ProcessBuilder(new String[]{"/bin/bash", "-c", "./test_elanprv2.2.sh");
File output = new File("_", fileName + ".txt");
pb.redirectOutput(output);
System.out.println("wrote text");
pb.directory(dir);
Process start = pb.start();
start.destroy();
} catch (Exception e) {
e.printStackTrace();
System.out.println("failed to write text");
}
您的大多数问题都是由于误解了流程的工作方式。这些概念不是Java概念;使用其他语言也会遇到同样的问题。
首先,您在进程运行之前,甚至可能在它开始之前就破坏了它。这是因为pb.start()
启动了这个过程,然后你立即破坏了它,没有给它完成的机会。
你根本不需要破坏进程。让它结束吧:
Process start = pb.start();
start.waitFor();
所有过程都有自己的标准输入和标准输出。再次强调,这不是Java的概念;这是Unix和Windows操作系统长期以来的基本特性。
通常,当进程通过将信息写入其标准输出来打印信息时。这实际上就是Java的System.out.println
所做的。在Unix shell(和Windows)中,>
字符将进程的标准输出重定向到一个文件;该程序仍然写入其标准输出,而不知道操作系统正在将该输出发送到终端以外的目的地。由于这是一个基本的操作系统功能,Java可以为您完成:
ProcessBuilder pb =
new ProcessBuilder("/bin/bash", "-c", "./test_elanprv2.2.sh");
pb.redirectOutput(new File(fileName + ".txt"));
同样,当一个进程想要获取输入时,它通常通过从标准输入中读取来实现。这与执行另一个命令不同。当你这样做时:
./test_elanprv2.2.sh > "$1"; sleep 1; q
您没有将q
发送到shell脚本。上面的命令等待shell脚本完成,然后执行一个sleep,然后尝试执行一个名为q
的程序(可能不存在)。
由于test_elanprv2.2.sh shell脚本可能通过读取其标准输入来接受命令,因此您希望将q
命令发送到该进程的标准输入:
ProcessBuilder pb =
new ProcessBuilder("/bin/bash", "-c", "./test_elanprv2.2.sh");
pb.redirectOutput(new File(fileName + ".txt"));
Process start = pb.start();
Thread.sleep(1000);
try (Writer commands = new OutputStreamWriter(start.getOutputStream())) {
commands.write("qn");
}
// Caution: Call this AFTER writing commands. You don't want to write
// to the standard input of a process that has already finished!
start.waitFor();