Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用java执行脚本,读取错误和输出流_Java_Shell - Fatal编程技术网

用java执行脚本,读取错误和输出流

用java执行脚本,读取错误和输出流,java,shell,Java,Shell,我希望能够从java执行一个外部命令,例如“ls”,并以字符串的形式实时获取输出,包括输出流和错误流,并且按照它们生成的顺序 因此,如果命令的输出类似于: blah <- to stdout foo <- to stderr bar <- to stdout 朴素的方法会产生以下结果之一: blah bar (即无标准输出) 或: (即重新排列顺序,使stdout和stderr消息不会相互交错)。使用ProcessBuilder并设置redire

我希望能够从java执行一个外部命令,例如“ls”,并以字符串的形式实时获取输出,包括输出流和错误流,并且按照它们生成的顺序

因此,如果命令的输出类似于:

blah     <- to stdout
foo      <- to stderr
bar      <- to stdout
朴素的方法会产生以下结果之一:

blah
bar
(即无标准输出)

或:


(即重新排列顺序,使stdout和stderr消息不会相互交错)。

使用
ProcessBuilder
并设置
redirectErrorStream(true)
使用
ProcessBuilder
并设置
redirectErrorStream(true)
这并非总是可能的

如果使用
ProcessBuilder
API,可以将
stdout
stderr
流合并为一个流(使用
redirectErrorStream(true)
),因此可以在一个
InputStream
中读取两个输出。但这意味着您无法区分数据最初来自哪个流

如果将
stdout
stderr
读作两个流,则需要NIO或两个Java线程。在这两种情况下,处理一个输出会阻塞另一个输出(或者说,另一个流不会被及时处理)。这将导致交换线路

如果子进程不刷新输出,而您使用管道,则情况会变得更糟,因为
stdout
将以4KB块的形式发送到您的进程,而
stderr
通常会逐行到达

恐怕没有独立于平台的解决方案。如果您只需要一个在Unix上工作的解决方案,那么可以使用Pseudo TTYs()来模拟shell,但这些都很难从Java中设置,因为您需要调用OS函数


一种方法可能是使用Perl或类似工具在PTY中运行命令(这会导致stdout变成行缓冲),从那里读取stdout和stderr,并在每行前面加上stdout的
1
,stderr的
2

这并不总是可能的

如果使用
ProcessBuilder
API,可以将
stdout
stderr
流合并为一个流(使用
redirectErrorStream(true)
),因此可以在一个
InputStream
中读取两个输出。但这意味着您无法区分数据最初来自哪个流

如果将
stdout
stderr
读作两个流,则需要NIO或两个Java线程。在这两种情况下,处理一个输出会阻塞另一个输出(或者说,另一个流不会被及时处理)。这将导致交换线路

如果子进程不刷新输出,而您使用管道,则情况会变得更糟,因为
stdout
将以4KB块的形式发送到您的进程,而
stderr
通常会逐行到达

恐怕没有独立于平台的解决方案。如果您只需要一个在Unix上工作的解决方案,那么可以使用Pseudo TTYs()来模拟shell,但这些都很难从Java中设置,因为您需要调用OS函数


一种方法可能是使用Perl或类似工具在PTY中运行命令(这会导致stdout变成行缓冲),从那里读取stdout和stderr,并在每一行前面加上stdout的
1
,stderr的
2

我建议您使用它们,因为它们是更复杂的API

请参阅:您可以:

  • 为子流程设置当前工作目录
  • 提供一组传递给子流程的环境变量
  • 使用ExecuteStreamHandler捕获stdout和stderr的子流程输出
  • 使用ExecuteWatchLog终止长时间运行的进程
  • 定义一组预期的退出值
  • 当主进程使用ProcessDestroyer终止时,终止任何已启动的进程

    • 我建议您使用,因为它们是更复杂的API

      请参阅:您可以:

      • 为子流程设置当前工作目录
      • 提供一组传递给子流程的环境变量
      • 使用ExecuteStreamHandler捕获stdout和stderr的子流程输出
      • 使用ExecuteWatchLog终止长时间运行的进程
      • 定义一组预期的退出值
      • 当主进程使用ProcessDestroyer终止时,终止任何已启动的进程

      用法:用法:使用起来似乎非常复杂,而且没有明显的文档记录。它做了我用ProcessBuilder做不到的事情吗?它看起来使用起来非常复杂,而且没有明显的文档记录。它做了我不能用ProcessBuilder做的事情吗?
      blah
      bar
      
      blah
      bar
      foo