Ruby,exec,system和%x()或反引号之间的区别


370

以下Ruby方法有什么区别?

execsystem%x()反引号

我知道它们用于通过Ruby以编程方式执行终端命令,但是我想知道为什么有三种不同的方法来执行此操作。


1
:这些命令,和许多人一样,都在文档解释相当不错的exec 系统 反引号
探究性

1
关于该主题,有一篇很棒的Ruby Quicktips文章:执行shell命令
西蒙·佩雷佩里察

6
由于有人刚刚挖了这个旧线程,因此“ Ruby Unix Processes”对于那些对以下主题感兴趣的Rubyists来说
Michael Kohl

1
我很惊讶都没有提到答案sh
丹尼斯

@Dennis当我提出这个问题时,ruby 1.9.3 *没有发布。
布莱克先生

Answers:


411

系统

system方法调用系统程序。您必须提供命令作为此方法的字符串参数。例如:

>> system("date")
Wed Sep 4 22:03:44 CEST 2013
=> true

调用程序将使用当前的STDINSTDOUTSTDERR你的Ruby程序对象。事实上,实际的回报值是truefalsenil。在示例中,日期是通过的IO对象打印的STDINtrue如果进程以零状态退出,false如果进程以非零状态退出且nil执行失败,则该方法将返回。

另一个副作用是将全局变量$?设置为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可以使用字符串插值。

执行

通过使用Kernel#exec当前进程(您的Ruby脚本),将其替换为通过调用的进程exec。该方法可以将字符串作为参数。在这种情况下,字符串将进行外壳扩展。当使用多个参数时,第一个参数用于执行程序,以下参数作为要调用的程序的参数提供。

打开3

有时,所需的信息会写到标准输入或标准错误中,您也需要对这些信息进行控制。这里Open3.popen3就派上用场了:

require 'open3'

Open3.popen3("curl http://example.com") do |stdin, stdout, stderr, thread|
   pid = thread.pid
   puts stdout.read.chomp
end

3
而对于如何通话手柄更细粒度的控制STDINSTDOUTSTDERR,考虑Open3.popen3代替; 例如,请参阅stackoverflow.com/a/10922097/258662
cboettig 2014年

1
感谢您提到反引号支持字符串插值,这解决了我的问题。
adg

244

这是基于此答案的流程图。也参见,使用script以模拟终端

在此处输入图片说明


3
这不是那么简单。在我的情况下,“可以(并且需要)阻塞直到过程完成”,然后使用popen3检查STDOUT / STDERR输出。
Nakilon '16

通过将其包装在while循环中,始终可以使非阻塞调用(有效地)阻塞。您不能如此轻松地将阻止呼叫转换为非阻止呼叫。
伊恩(Ian)

106

他们做不同的事情。 exec用新流程替换当前流程,永不返回system调用另一个进程,并将其退出值返回给当前进程。使用反引号将调用另一个进程,并将该进程的输出返回到当前进程。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.