2

这是一些Ruby代码:

puts %x{ pstree #{$$} }   # never forks
puts %x{ pstree '#{$$}' } # forks on amd64 only

在 32 位 Ubuntu Dapper 上,我得到以下输出:

t.rb---pstree
t.rb---pstree

这对我来说很有意义。但是在 64 位 Ubuntu Hardy 上,我得到了这个:

t.rb---sh---pstree
t.rb---pstree

这里显示的是 Ruby 在执行前分叉只是其中一种情况。当我将代码放在一个文件中并在 strace -fF 下运行它时,它似乎在 64 位 Hardy 上调用clone()(like fork()) before execve(),而在 32 位 Dapper 上它没有这样的事情。

我的 Ruby 版本是:

ruby 1.8.4 (2005-12-24) [i486-linux]
ruby 1.8.6 (2007-09-24 patchlevel 111) [x86_64-linux]

我应该尝试更多地混合和匹配解释器、操作系统和字长,但现在这并不容易,因为我不管理这些机器。也许你们中的某个人可以告诉我这些命令在 64 位系统上的区别是什么,更不用说为什么它们在 32 位系统上的工作方式相同了。

4

2 回答 2

2

当 %x 与单个参数一起使用时(就像您正在做的那样),Ruby 执行 shell 扩展。

这是我对发生了什么的猜测:

Ruby scans the command to determine if there are any special characters that would result in the need to perform shell expansion, if so it calls the shell to do that. In the second example the single quotes are enough to make Ruby want to call the shell to do the expansion, hence the fork. In the first example Ruby can determine that shell expansion is not needed as the command contains no special characters (after variable expansion), hence no fork. The difference between the two versions probably has to do with an internal change in how ruby tries to determine is shell expansion is needed. I get a fork for the second example on ruby 1.8.5 on a 32-bit machine.

[EDIT]

Okay, I took a look at the source code for ruby 1.8.4 and 1.8.6 and both versions use the same criteria to determine whether or not to call a shell to perform shell expansion, if any of the following characters exist in the command line the shell will be invoked when one argument to %x is provided:

*?{}[]<>()~&|\\$;'`"\n

Ruby is actually calling the shell in both cases (in example that contains the quotes), the reason you are seeing different outputs from pstree is due to differences in the the sh command on the different machines, one calls fork, the other doesn't. To see this for yourself, run this command on both machines:

/bin/sh -c "pstree $$"

This is the command that Ruby is using to execute pstree in the example with quotes on both machines. You should see bash---pstree on the 32-bit machine and bash---sh---pstree on the other one.

So now I'm curious, what led you to discover this difference and is it causing a problem?

于 2008-10-18T00:27:13.293 回答
1

I went through this situation by developing an asynchronous processor work that has a series of subprocesses(fork), and it happened when the master was in the foreground and received a SIGINT.

I run: puts "the result is %(monster-delayed-job)"

and the output was only: "the result is "

  • Yes, Im "trap" SIGINT in the master

Andre

于 2011-09-24T18:47:09.837 回答