以下Ruby方法有什么区别?
exec
,system
和%x()
或反引号
我知道它们用于通过Ruby以编程方式执行终端命令,但我想知道为什么有三种不同的方法来执行此操作。
答案 0 :(得分:377)
<强>系统强>
system
方法调用系统程序。您必须将此命令作为字符串参数提供给此方法。例如:
>> system("date")
Wed Sep 4 22:03:44 CEST 2013
=> true
调用的程序将使用Ruby程序的当前STDIN
,STDOUT
和STDERR
对象。实际上,实际返回值为true
,false
或nil
。在示例中,日期是通过STDIN
的IO对象打印的。如果进程以零状态退出,则该方法将返回true
,如果进程退出非零状态,则返回false
,如果执行失败,则返回nil
。
另一个副作用是全局变量$?
设置为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
可以替代反引号样式。它也会返回输出。与其亲属%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
答案 1 :(得分:220)
这是基于this answer的流程图。另请参阅using script
to emulate a terminal。
答案 2 :(得分:100)
他们做不同的事情。 exec
使用新流程替换当前流程,永不返回。 system
调用另一个进程,将其退出值返回到当前进程。使用反引号调用另一个进程,将该进程的输出返回到当前进程。