使用Groovy,如何将多个shell命令连接起来?

22

如何使用Groovy及其java.lang.Process支持将多个shell命令串联在一起?

考虑此bash命令(假设您的用户名为foo):


ps aux | grep ' foo' | awk '{print $1}'

这将打印出用户名 - 一行用于与您的用户帐户相关的某些进程。

使用Groovy,ProcessGroovyMethods文档和代码表示我应该能够执行以下操作以实现相同的结果:

def p = "ps aux".execute() | "grep ' foo'".execute() | "awk '{print $1}'".execute()
p.waitFor()
println p.text

然而,除了这个,我无法得到其他任何文本输出:

def p = "ps aux".execute()
p.waitFor()
println p.text

一旦我开始使用管道,println就不会打印任何内容。

有何想法?

4个回答

34

这对我起作用:

def p = 'ps aux'.execute() | 'grep foo'.execute() | ['awk', '{ print $1 }'].execute()
p.waitFor()
println p.text

由于未知原因,awk的参数不能仅用一个字符串发送(我不知道为什么!也许bash会以不同方式引用某些内容)。如果您使用命令倾销错误流,则会看到与awk脚本编译有关的错误。

编辑:

  1. "-string-".execute() 委托给 Runtime.getRuntime().exec(-string-)
  2. 处理包含空格的参数是bash的工作,并在参数周围添加 '或"。 Runtime.exec或操作系统不知道这些引号
  3. 执行 "grep 'foo'".execute() 执行grep命令,第一个参数为 ',第二个参数为 foo':这是无效的。对于awk同样如此

虽然@tim_yates的答案以不同的方式解决了我的特定问题(我非常感激),但这个答案回答了OP关于Groovy的“or”运算符和“Process”对象的问题,所以我会授予它。谢谢! - Les Hazlewood

17
您可以这样做,只需让shell自行排序:
// slash string at the end so we don't need to escape ' or $
def p = ['/bin/bash', '-c', /ps aux | grep ' foo' | awk '{print $1}'/].execute()
p.waitFor()
println p.text

是的,我可以这样做,也许这是我需要走的路,但你知道为什么“or”方法在文档中定义时不起作用吗? - Les Hazlewood
1
这与awk有关。不确定是什么问题,但它不喜欢以这种方式运行。 - tim_yates
有趣的是,斜杠的方法起作用了。使用双引号却没有。去想吧! - Les Hazlewood
这个回答并不是错误的,但它并没有回答原问题:如何在Groovy中使用|运算符连接Process对象。你只能通过bash执行一个命令,并且是bash将进程连接起来,而不是Groovy。 - Jérémie B
@tim_yates 是的,我认为这与awk或嵌套的单引号有关。使用斜杠字符串解决了我的问题,所以我想我将来会使用它。不幸的是,Groovy管道的问题仍然存在 :/ - Les Hazlewood

8
这对我很有帮助。
def command = '''
    ps aux | grep bash | awk '{print $1}'
'''
def proc = ['bash', '-c', command].execute()
proc.waitFor()
println proc.text

如果您想运行多个命令,可以将它们添加到命令中。

def command = '''
    ls -ltr
    cat secret
'''
def proc = ['bash', '-c', command].execute()
proc.waitFor()
println proc.text

这与@tim_yates上面的答案相同 - 他只是使用斜杠字符串而不是heredoc :) - Les Hazlewood
1
@LesHazlewood 对我来说,这个可行,而斜杠字符串则不行。 - selle

0
如果您想要异步操作,我建议使用

 proc.consumeProcessOutputStream(new LineOrientedOutputStream() {
        @Override
        protected void processLine(String line) throws IOException {
           println line
        }
    }
    );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接