我正在尝试在我的Java程序中运行以下命令
Runtime.getRuntime().exec("ls -lrt service/logs/post/level2.log | awk '{print $9}'");
or
Runtime.getRuntime().exec("ls -lrt service/logs/post/level2* | awk '{print $9}'");
它给了我以下错误
ls: 0653-341 The file | does not exist. ls: 0653-341 The file awk does not exist. ls: 0653-341 The file '{print does not exist. ls: 0653-341 The file $9}' does not exist.
请帮助我
答案 0 :(得分:9)
管道是基于shell的构造,而不是实际的可运行命令。我看到它有两种选择:
ls
命令,获取其OutputStream
的句柄,然后调用awk
将第一个Process
的输出连接到第二个Process
输入流-c
参数。这样,所有管道都在 单个过程中完成。对于基于令牌的错误,您应该使用字符串数组调用这些命令;每个元素代表命令行的标记。所以试试,例如:
Runtime.getRuntime().exec(new String[] { "ls", "-lrt", "service/logs/post/level2.log" });
以便调用ls命令。在这种情况下,我不认为这是严格必需的,但它将用于awk
命令,因为Java不知道任何关于特定于shell的引用规则,所以默认情况下标记空格字符上的单字符串输入。这就是你的awk脚本分成两部分的原因。
编辑(以回应评论):在第一个选项中,我的意思是你能够在Java中自己管理两个进程之间的输出。
想象一下,如果你已经创建了一个过程:
Process ls = Runtime.getRuntime().exec("ls -lrt service/logs/post/level2.log");
现在,这个过程将运行并生成一些输出(我们知道它将是描述该文件的一行)。我们可以像这样得到这个输出的流:
InputStream lsOut = ls.getInputStream();
现在,我们想要运行awk进程:
Process awk = Runtime.getRuntime().exec(new String[] { "awk", "{print $9}"});
awk进程当然会坐在等待输入的那一刻,因为它知道它将从stdin读取。因此,我们抓住它将要使用的输入流:
OutputStream awkIn = awk.getOutputStream();
现在,管道位 - 我们读取ls命令的输出并将其传递给awk的输入:
// TODO add buffering, error handling, probably run this in a separate thread
int datum = lsOut.read();
while (datum != -1)
{
awkIn.write(datum);
datum = lsOut.read();
}
这会读取ls
的输出(为了简单起见逐字节,使用字节数组缓冲区要快得多,但我试图简单地说明这个概念)并将其写入{{{}的输入。 1}}。
然后,只需要阅读awk
进程的输出并按照您认为合适的方式处理它。