2015-05-22 42 views
1

我有一个调用(使用调用Runtime.getRuntime()EXEC。)bash脚本这样的Java应用程序:调用Bash交互

read -e -p "Are you sure you want to do this? (y/n)? " 
echo "$REPLY" 

的问题是,我从来没有提示部分从bash脚本(“你确定...”文本)。

有没有办法从Java调用交互式bash脚本,以便我可以读取它的输出?我需要它,以便能够确定我正在被脚本询问哪个问题(实际上它是一个比这里描述的更大的脚本)。

如果我通过SSH通道使用-t标志(t标志上的重音,没有它不会工作)运行从Java通道的过程,它工作正常。但是我想避免为了正确运行脚本,或者更准确地说,要正确地读取其输出,而不得不自己ssh。

-p prompt 
    Display prompt on standard error, without a trailing new‐ 
    line, before attempting to read any input. The prompt is 
    displayed only if input is coming from a terminal. 

所以你应该确保你也捕获标准错误,如果你想看到这样的信息:在谈论read

回答

1

显示在stdout好的,这里的交易。

正如Eric所指出的,只有当输入来自终端时才会显示提示,所以我需要一个伪终端来欺骗bash脚本。我设法通过使用JPty库来实现。

+0

谢谢你的这个链接,这对我也有很大的帮助。我不想包含整个库,所以我只是添加了一行'processBuilder.environment()。put(“TERM”,“xterm”);',这使得'ProcessBuilder'就像是一个终端。 – dounyy

1

从bash的手册页。你可以通过添加2>&1来从java中调用它,但我不确定java的调用是否会遵守它。

如果您使用ProcessBuilder来调用它,您应该在进程上添加对redirectErrorStream(true)的调用,以通过标准输出读取来获取stderr。

我还没有试图自己验证,但this page建议将进程的标准输出重定向到/dev/tty,以使其认为它直接连接到java进程的tty。所以你应该添加一个&>/dev/tty来将stdout和stderr重定向到/dev/tty,并且希望它能够显示出来 - 尽管这可能会显示在控制Java进程的stderr而不是子进程中。我对此不太确定。

如果你不能做到这一点,另一个要考虑的是将尝试修改脚本,所以它的echo -n "<msg>"; read REPLY这样的提示将echo,而不是完全不受read

+0

嗯,是的,提示转到'stderr',但我认为你忽略了这些文档中最重要的部分:“仅当输入来自终端时才显示提示。”在OP描述的情况下,输入*不来自终端。 –

+0

@JohnBollinger真的,尽管我从这个用户的一个早期问题中应用了一些知识,而这个知识是通过一个使用'-t'的ssh会话来调用的,所以它实际上应该在这种情况下认为它有一个终端。如果情况的这一部分发生了变化,那么你是对的,这不会有什么帮助 –

+0

对于这个问题,很抱歉让我们陷入困境:从Java调用ssh -t完全可以。我想避免ssh -t部分,但没有它,我不会从bash得到输出。 – slouc