以下 Ruby 方法有什么区别?
exec
、system
和 %x()
或 反引号
我知道它们用于通过 Ruby 以编程方式执行终端命令,但我想知道为什么有三种不同的方法可以做到这一点。
sh
。
系统
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>
反引号
Backticks (``) 调用系统程序并返回其输出。与第一种方法相反,命令不是通过字符串提供的,而是通过将其放在反引号对中。
>> `date`
=> Wed Sep 4 22:22:51 CEST 2013
全局变量 $?
也是通过反引号设置的。使用反引号,您还可以使用字符串插值。
%X()
使用 %x
是反引号样式的替代方法。它也会返回输出。像它的亲戚 %w
和 %q
(以及其他)一样,只要括号样式的分隔符匹配,任何分隔符都足够了。这意味着 %x(date)
、%x{date}
和 %x-date-
都是同义词。像反引号 %x
可以利用字符串插值。
执行
通过使用 Kernel#exec
,当前进程(您的 Ruby 脚本)将替换为通过 exec
调用的进程。该方法可以将字符串作为参数。在这种情况下,字符串将受到外壳扩展。当使用多个参数时,第一个参数用于执行程序,以下参数作为参数提供给要调用的程序。
打开3.popen3
有时所需的信息会写入标准输入或标准错误,您也需要控制这些信息。这里 Open3.popen3
派上用场了:
require 'open3'
Open3.popen3("curl http://example.com") do |stdin, stdout, stderr, thread|
pid = thread.pid
puts stdout.read.chomp
end
这是基于 this answer 的流程图。另见,using script
to emulate a terminal。
https://i.stack.imgur.com/1Vuvp.png
他们做不同的事情。 exec
用新进程替换当前进程并且永不返回。 system
调用另一个进程并将其返回其退出值给当前进程。使用反引号调用另一个进程并将该进程的输出返回到当前进程。
不定期副业成功案例分享
STDIN
、STDOUT
、STDERR
,请考虑使用Open3.popen3
;例如见stackoverflow.com/a/10922097/258662