1

我正在尝试在我的 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 文件 | 不存在。
ls: 0653-341 文件 awk 不存在。
ls: 0653-341 文件'{print 不存在。
ls: 0653-341 文件 $9}' 不存在。

请帮助我

4

1 回答 1

9

管道是基于 shell 的构造,而不是实际的可运行命令。在我看来,有两种选择:

  1. 在 Java 中自己做管道。首先调用ls命令,获取其句柄OutputStream,然后调用awk将第一个Process' 的输出连接到第二个Process' 输入流。
  2. 直接从 Java 调用 bash shell,将整个命令作为参数传递给 bash 的-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 进程当然会在等待输入的那一刻坐在那里,因为它知道它将从标准输入读取。因此,我们获取将要使用的输入流:

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(为简单起见,逐字节读取,使用字节数组缓冲区会快得多,但我试图简单地说明这个概念)并将其写入awk.

然后,只需读取awk流程的输出并按照您认为合适的方式处理它。

于 2010-06-22T12:32:05.183 回答