以下 Ruby 方法有什么不同之处?
exec
、system
和 %x()
或称为反引号
我知道它们都可以通过 Ruby 在程序中执行终端命令,但我想知道为什么会有三种不同的方法。
系统
system
方法调用一个系统程序。你需要将命令作为字符串参数提供给该方法。例如:
>> system("date")
Wed Sep 4 22:03:44 CEST 2013
=> true
被调用的程序将使用您的Ruby程序当前的STDIN
、STDOUT
和STDERR
对象。实际的返回值只能是true
、false
或nil
。在示例中,日期是通过STDIN
的IO对象打印出来的。如果进程以零状态退出,则该方法将返回true
;如果进程以非零状态退出,则返回false
;如果执行失败,则返回nil
。
从Ruby 2.6开始,传递exception: true
将引发异常而不是返回false
或nil
:
>> system('invalid')
=> nil
>> system('invalid', exception: true)
Traceback (most recent call last):
...
Errno::ENOENT (No such file or directory - invalid)
另一个副作用是,全局变量$?
被设置为一个Process::Status
对象。该对象将包含有关调用本身的信息,包括所调用进程的进程标识符(PID)和退出状态。
>> system("date")
Wed Sep 4 22:11:02 CEST 2013
=> true
>> $?
=> #<Process::Status: pid 15470 exit 0>
反引号
反引号(``)调用系统程序并返回其输出。与第一种方法不同的是,命令不是通过字符串提供的,而是将其放在反引号对中。
>> `date`
=> Wed Sep 4 22:22:51 CEST 2013
全局变量$?
也可以通过反引号进行设置。使用反引号时,您还可以使用字符串插值。
%x()
使用%x
是反引号样式的替代方法。它也会返回输出结果。与其他相关的%w
和%q
一样,只要括号样式的定界符匹配即可使用任何定界符。这意味着%x(date)
、%x{date}
和%x-date-
都是同义词。与反引号一样,%x
也可以使用字符串插值。
exec
通过使用Kernel#exec
,当前进程(Ruby脚本)将被用exec
调用的进程所替换。该方法可以接受一个字符串作为参数。在这种情况下,该字符串将遵循Shell扩展。当使用多个参数时,第一个参数用于执行程序,其余的参数则用作要调用的程序的参数。
Open3.popen3
有时需要将所需的信息写入标准输入或标准错误,您还需要控制它们。这时就可以使用Open3.popen3
:
require 'open3'
Open3.popen3("curl http://example.com") do |stdin, stdout, stderr, thread|
pid = thread.pid
puts stdout.read.chomp
end
STDIN
、STDOUT
、STDERR
的方式,考虑使用 Open3.popen3
;可参考 https://dev59.com/cmgu5IYBdhLWcg3w_cBV#10922097。 - cboettig这两者功能不同。exec
替换当前进程为新的进程,并且 从不返回。 system
调用另一个进程,并返回该进程的退出值给当前进程。使用反引号则会调用另一个进程,并将该进程的输出结果返回给当前进程。
在我的情况下,这个方法有效。
output = `nmap localhost`
这个方法将输出保存到变量中,因此答案是使用 `` 而不是 system。
sh
。 - Dennis