为什么java.lang.Process.getInputStream()返回的结果与命令行调用不同?

为什么java.lang.Process.getInputStream()返回的结果与命令行调用不同?,java,shell,cmd,command-line,Java,Shell,Cmd,Command Line,我尝试从存档中提取文件 我使用命令rarx 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&q

我尝试从存档中提取文件

我使用命令rarx 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);
}
它返回相同的单词,但没有输入密码

我知道,我可以通过命令-p检查存档中存在的密码,如所述

但是我不明白为什么命令行执行和java进程执行有一些不同

谁能解释一下:

为什么会这样? 如何正确执行命令,获得完整的示例,欢迎链接?
没有一个真理是完全正确的。一些例子:

可执行文件可以根据连接的终端改变其行为

输出也将根据您收听的输出流而改变。可执行文件可以打印到stdout或stderr,而这些是不同的流,您可以听其中一个,也可以听两个,也可以听不到。并且,正如在另一个答案中所指出的,linux密码提示符可以使用direct/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可执行文件显式地找到终端并在那里询问,或者如果不能,则确定会话不是交互式的,并拒绝提示输入这样的密码。它不会故意向标准输出或标准错误发送“输入密码”提示。它这样做的原因,特别是为了停止你正在做的事情。这可能有点过分热情,但你们得和亚历山大·罗沙尔和朋友们谈谈

解决办法是完全重写。用法:例如。您最终将获得更强大、更灵活的功能。

输入密码不会显示在标准输出中,也不会从标准输入中读取。这是Unix/Linux程序中的一种长期做法,用于确保密码的安全:直接从控制台/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

您将考虑将密码暴露给系统上的临时观察员的风险。

我不知道如何自动执行直接从控制台读取的外部命令


但是,使用Java而不是外部命令来读取rar归档文件的地址。似乎是一个受欢迎的选择。我还没有用过它,所以我不能说它的有效性。

看一看[如果您询问代码,请提供您用于获取output@eis好的,我编辑了我的问题并添加了一些代码。如果你按字符而不是按行阅读呢?@powdersinconstructoring根据你的代码更新了我的答案。我想,根据这个问题,OP已经知道-p开关,但仍然想知道为什么他看不见在他的用例中,您的回复的第一段给出答案的密码提示to@eis谢谢,你说得对。我在回答中更新了语言以确认这一点。感谢提供重要的安全信息!!!1据我所知,如果我想得到与shell结果相同的结果,我需要在交互模式下运行该命令。是还是否?2,你能给我一个命令的例子吗,我需要在java中使用它,以得到相同的结果?3我尝试读取字符,结果是same@BestowsInConstructoring1可能吧。有些可执行文件就是这样工作的,不知道rar可执行文件在内部做什么。2&3那么你就走运了,想不出用java能得到同样的结果的方法。