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


当前回答

不确定shell命令。我使用以下命令将系统命令的输出捕获到变量val中:

val = capture(:stdout) do
  system("pwd")
end

puts val

缩短版本:

val = capture(:stdout) { system("pwd") }

捕获方法由active_support/core_ext/kernel/reporting.rb提供

类似地,我们也可以用:stderr捕获标准错误

其他回答

你也可以使用反勾操作符('),类似于Perl:

directoryListing = `ls /`
puts directoryListing # prints the contents of the root directory

如果你需要简单的东西,很方便。

你想要使用哪种方法取决于你想要完成什么;有关不同方法的更多细节,请查看文档。

如果你真的需要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)

您可以使用如下格式方法打印一些信息:

puts format('%s', `ps`)
puts format('%d MB', (`ps -o rss= -p #{Process.pid}`.to_i / 1024))

我喜欢的方法是使用%x文字,这使得在命令中使用引号很容易(而且易读!),如下所示:

directorylist = %x[find . -name '*test.rb' | sort]

在这种情况下,它将填充当前目录下的所有测试文件的文件列表,您可以按照预期进行处理:

directorylist.each do |filename|
  filename.chomp!
  # work with file
end