【发布时间】:2015-04-19 17:06:16
【问题描述】:
我正在尝试(但失败了)找出如何在 Java 中运行完全交互式的 shell 程序。
这是场景:
我有一个用 Java 编写的跨平台大型 GUI 应用程序。为此,我正在尝试添加一个交互式命令行环境以无头运行。事情的那一面都很好,花花公子。然而,主 GUI 的功能之一是编辑文件。现在,对于命令行界面,我希望能够执行外部编辑器来编辑文件,然后在保存并退出后返回到我所在的位置。例如,在 Linux 上它可能会执行“vi /path/to/file”。
那么我怎样才能以键盘和显示器与应用程序完全交互的方式执行该命令呢?我不希望它在后台运行。我不希望它通过 Java 重定向 IO,我只希望一个命令“在前台”运行直到它存在。
就像我在 C 中使用 system() 函数一样。
到目前为止,我发现的所有内容都在后台运行命令或通过 Java 管道传输 IO,这不适用于交互式(非行模式)应用程序。
哦,还有最后一个警告:我受限于 Java 1.6 兼容性,所以我不能用 ProcessBuilder 做一些花哨的事情。
这是强制性的 SSCCE:
class exetest {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec("vi");
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
}
我希望 Runtime.getRuntime().exec() 在我完成 vi 之前一直阻塞,并且在此期间所有键盘输入都会直接(众所周知的RAW)一直到 vi并且所有屏幕输出都会直接返回给用户,不会被触及。
这就是我在 C 中实现它的方式:
void main() {
system("vi");
}
更新:
这达到了预期的结果,但是 a) 仅限于 Linux / OSX(不是什么大问题,但如果能跨平台就好了),并且 b) 是一个糟糕的组合:
import java.io.*;
class exetest {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec("/bin/bash");
OutputStream stdin = p.getOutputStream();
PrintWriter pw = new PrintWriter(stdin);
pw.println("vi < /dev/tty > /dev/tty");
pw.close();
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
}
【问题讨论】:
-
你想要github.com/ronniedong/Expect-for-Java这样的东西吗?
-
不,我不知道。我不希望 Java 与执行的程序交互,我希望用户与之交互。所以他们输入
edit myfile,它执行vi /path/to/myfile,用户编辑文件就像他们在终端输入vi /path/to/myfile一样。