为什么 java.lang.Process.getInputStream() return 与命令行调用的结果不同?
Why does java.lang.Process.getInputStream() return different result than a command line call?
我尝试从存档中提取文件
我使用命令rar x file_to_extact.rar /tmp/some_dir
所以当我在命令行中执行它时,它显示 RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal...
好的
但是当我在java进程中执行它时
Process process = new ProcessBuilder(new String[] { "rar", "x", "file_to_extact.rar", "/tmp/some_dir" }).start();
BufferedReader inputReader = new BufferedReader(new
InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new
InputStreamReader(process.getErrorStream()));
String string = null;
while ((string = inputReader.readLine()) != null) {
System.out.println(string);
}
while ((string = errorReader.readLine()) != null) {
System.out.println(string);
}
它return相同的词但没有Enter password...
我知道,我可以通过命令 -p
检查存档中是否存在密码,如所述 here
但是我不明白为什么命令行执行和java进程执行有一些不同
谁能解释一下:
- 为什么会这样?
- 如何正确的执行命令,得到完整的(例子,欢迎链接)?
没有“满”这个道理。一些例子:
可执行文件可以根据连接的终端更改其行为(特别是,if it's interactive or not)
输出也会根据您收听的输出流而改变。可执行文件可以打印到 stdout 或 stderr,它们是不同的流,您可以听一个或另一个,两者或 none。并且,如其他答案所述,linux 密码提示可以使用直接 /dev/tty 作为密码作为安全功能,因此不使用 stdout 或 stderr。
本案可能与前者有关。可执行文件检测到您没有使用交互式 shell 并相应地修改其行为。
但是,对于这种情况,也可能是您没有从 processbuilder 正确获取输出。
您似乎在此处获取完整行:
while ((string = inputReader.readLine()) != null) {
System.out.println(string);
}
但密码提示不是整行。获取所有字符可能会使它可见:
int r;
while ((r = reader.read()) != -1) {
char ch = (char) r;
System.out.print(ch);
}
注意:上面的示例仅适用于 ascii 字符,如果您需要支持更大的字符集,则需要更多编码。这只是为了演示逐字阅读。
这是因为 rar
可执行文件显式找到 a/the 终端并在那里询问,或者如果不能,则确定该会话不是交互式的,并拒绝像这样提示输入密码.它不会故意将 'Enter password' 提示发送到标准输出(或标准错误)。它这样做的原因是专门为了停止你正在做的事情。这可能过于热心了,但您必须与 Alexander Roshal 和朋友一起解决这个问题。
解决办法是完全重写。使用:junrar 例如。您最终会得到更加健壮和灵活的东西。
Enter password
没有显示在标准输出中,也没有从标准输入中读取。这是 Unix/Linux 程序中长期存在的做法,以确保密码安全:直接从 console/tty 读取密码(这也是程序防止键入的密码被回显的方式)。
虽然您可以将密码作为参数发送到 -p
命令行选项,但请注意,这是非常不安全的,因为它会将密码暴露给检查进程列表的任何其他用户。
new ProcessBuilder("rar", "x", "-p" + password, "file_to_extact.rar", "/tmp/some_dir")
同样,这是非常不安全的。当命令是 运行 时,任何用户都可以检查进程,并且会显示如下内容:
PID TTY STAT TIME COMMAND
8732 pts/3 S+ 0:00 rar x -pswordfish123 file_to_extact.rar /tmp/some_dir
您需要考虑将密码暴露给系统上的偶然观察者的风险。
我不知道有什么方法可以自动执行直接从控制台读取的外部命令。
但是,this question addresses using Java, rather than an external command, to read a rar archive. junrar 似乎是一个受欢迎的选择。 (我没用过,所以不好说。)
我尝试从存档中提取文件
我使用命令rar x file_to_extact.rar /tmp/some_dir
所以当我在命令行中执行它时,它显示 RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal...
好的
但是当我在java进程中执行它时
Process process = new ProcessBuilder(new String[] { "rar", "x", "file_to_extact.rar", "/tmp/some_dir" }).start();
BufferedReader inputReader = new BufferedReader(new
InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new
InputStreamReader(process.getErrorStream()));
String string = null;
while ((string = inputReader.readLine()) != null) {
System.out.println(string);
}
while ((string = errorReader.readLine()) != null) {
System.out.println(string);
}
它return相同的词但没有Enter password...
我知道,我可以通过命令 -p
检查存档中是否存在密码,如所述 here
但是我不明白为什么命令行执行和java进程执行有一些不同
谁能解释一下:
- 为什么会这样?
- 如何正确的执行命令,得到完整的(例子,欢迎链接)?
没有“满”这个道理。一些例子:
可执行文件可以根据连接的终端更改其行为(特别是,if it's interactive or not)
输出也会根据您收听的输出流而改变。可执行文件可以打印到 stdout 或 stderr,它们是不同的流,您可以听一个或另一个,两者或 none。并且,如其他答案所述,linux 密码提示可以使用直接 /dev/tty 作为密码作为安全功能,因此不使用 stdout 或 stderr。
本案可能与前者有关。可执行文件检测到您没有使用交互式 shell 并相应地修改其行为。
但是,对于这种情况,也可能是您没有从 processbuilder 正确获取输出。
您似乎在此处获取完整行:
while ((string = inputReader.readLine()) != null) {
System.out.println(string);
}
但密码提示不是整行。获取所有字符可能会使它可见:
int r;
while ((r = reader.read()) != -1) {
char ch = (char) r;
System.out.print(ch);
}
注意:上面的示例仅适用于 ascii 字符,如果您需要支持更大的字符集,则需要更多编码。这只是为了演示逐字阅读。
这是因为 rar
可执行文件显式找到 a/the 终端并在那里询问,或者如果不能,则确定该会话不是交互式的,并拒绝像这样提示输入密码.它不会故意将 'Enter password' 提示发送到标准输出(或标准错误)。它这样做的原因是专门为了停止你正在做的事情。这可能过于热心了,但您必须与 Alexander Roshal 和朋友一起解决这个问题。
解决办法是完全重写。使用:junrar 例如。您最终会得到更加健壮和灵活的东西。
Enter password
没有显示在标准输出中,也没有从标准输入中读取。这是 Unix/Linux 程序中长期存在的做法,以确保密码安全:直接从 console/tty 读取密码(这也是程序防止键入的密码被回显的方式)。
虽然您可以将密码作为参数发送到 -p
命令行选项,但请注意,这是非常不安全的,因为它会将密码暴露给检查进程列表的任何其他用户。
new ProcessBuilder("rar", "x", "-p" + password, "file_to_extact.rar", "/tmp/some_dir")
同样,这是非常不安全的。当命令是 运行 时,任何用户都可以检查进程,并且会显示如下内容:
PID TTY STAT TIME COMMAND
8732 pts/3 S+ 0:00 rar x -pswordfish123 file_to_extact.rar /tmp/some_dir
您需要考虑将密码暴露给系统上的偶然观察者的风险。
我不知道有什么方法可以自动执行直接从控制台读取的外部命令。
但是,this question addresses using Java, rather than an external command, to read a rar archive. junrar 似乎是一个受欢迎的选择。 (我没用过,所以不好说。)