如何从Ruby程序内部调用shell命令?然后如何将这些命令的输出返回到Ruby中?


当前回答

在这些机制之间进行选择时需要考虑的一些事情是:

你只是想要stdout还是 也需要stderr ?甚至 分离出来吗? 你的产出有多大?你想要 将整个结果保存在内存中? 你想读一些你的吗 在子进程静止时输出 跑步吗? 你需要结果代码吗? 你需要一个Ruby对象吗 表示流程并允许您 按需杀死它?

您可能需要简单的反撇号(' ')、system()和IO。popen到成熟的Kernel.fork/Kernel。执行IO。pipe和IO.select。

如果子进程执行时间过长,您可能还想在混合过程中加入超时。

不幸的是,这在很大程度上取决于情况。

其他回答

如果你真的需要Bash,请参考“最佳”答案中的注释。

首先,请注意,当Ruby调用shell时,它通常调用/bin/sh,而不是Bash。在所有系统上/bin/sh不支持某些Bash语法。

如果你需要使用Bash,在你想要的调用方法中插入Bash -c "your Bash-only command":

quick_output = system("ls -la")
quick_bash = system("bash -c 'ls -la'")

测试:

system("echo $SHELL")
system('bash -c "echo $SHELL"')

或者如果您正在运行一个现有的脚本文件,如

script_output = system("./my_script.sh")

Ruby应该尊重shebang,但你总是可以使用

system("bash ./my_script.sh")

为了确保这一点,尽管/bin/sh运行/bin/bash可能会有轻微的开销,但您可能不会注意到。

我绝对不是Ruby专家,但我还是会试一试:

$ irb 
system "echo Hi"
Hi
=> true

你还应该能够做以下事情:

cmd = 'ls'
system(cmd)

不要忘记使用spawn命令创建一个后台进程来执行指定的命令。你甚至可以使用Process类和返回的pid来等待它的完成:

pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid

pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid

文档说:这个方法类似于#system,但它不会等待命令完成。

下面是一个基于“何时在Ruby中使用启动子进程的每种方法”的流程图。另请参见“欺骗应用程序,使其误以为标准输出是终端,而不是管道”。

这不是一个真正的答案,但也许有人会发现它有用:

在Windows上使用TK GUI时,您需要从rubyw调用shell命令,您总是会有一个烦人的CMD窗口弹出不到一秒钟。

为了避免这种情况,你可以使用:

WIN32OLE.new('Shell.Application').ShellExecute('ipconfig > log.txt','','','open',0)

or

WIN32OLE.new('WScript.Shell').Run('ipconfig > log.txt',0,0)

两者都将ipconfig输出存储在log.txt中,但是不会弹出窗口。

你需要在你的脚本中要求'win32ole'。

system(), exec()和spawn()都会在使用TK和rubyw时弹出恼人的窗口。