Ruby %x 在 64 位 Linux 上分叉,但不在 32 位 Linux 上分叉,并且仅使用特定语法
以下是一些 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()
(如 fork()
) 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 位系统上工作相同了。
Here's some Ruby code:
puts %x{ pstree #{$} } # never forks
puts %x{ pstree '#{$}' } # forks on amd64 only
On 32-bit Ubuntu Dapper, I get this output:
t.rb---pstree
t.rb---pstree
Which makes sense to me. But on 64-bit Ubuntu Hardy, I get this:
t.rb---sh---pstree
t.rb---pstree
What's being shown here is that Ruby forks before exec'ing in just one of the cases. When I put the code in a file and run it under strace -fF, it appears that on 64-bit Hardy it calls clone()
(like fork()
) before execve()
, whereas on 32-bit Dapper it does no such thing.
My Ruby versions are:
ruby 1.8.4 (2005-12-24) [i486-linux]
ruby 1.8.6 (2007-09-24 patchlevel 111) [x86_64-linux]
I should try mixing & matching interpreters & OS's & word sizes more, but right now it's not easy since I don't administer these machines. Maybe someone among you can tell me what the difference even is between these commands on the 64-bit system, let alone why they work the same on the 32-bit one.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当 %x 与单个参数一起使用时(就像您所做的那样),Ruby 会执行 shell 扩展。
以下是我对发生的情况的猜测:
Ruby 扫描命令以确定是否有任何特殊字符会导致需要执行 shell 扩展,如果是的话,它会调用 shell 来执行此操作。 在第二个例子中,单引号足以让 Ruby 想要调用 shell 来进行扩展,因此出现了 fork。 在第一个示例中,Ruby 可以确定不需要 shell 扩展,因为命令不包含特殊字符(在变量扩展之后),因此没有 fork。 这两个版本之间的差异可能与 ruby 尝试确定是否需要 shell 扩展的内部变化有关。 我在 32 位机器上的 ruby 1.8.5 上获得了第二个示例的 fork。
[编辑]
好的,我查看了 ruby 1.8.4 和 1.8.6 的源代码,两个版本都使用相同的标准来确定是否调用 shell 来执行 shell 扩展(如果存在以下任何字符)在命令行中,当为 %x 提供一个参数时,将调用 shell:
Ruby 实际上在两种情况下都调用 shell(在包含引号的示例中),这就是您看到 pstree 不同输出的原因。 code> 是由于不同机器上的
sh
命令不同,一个调用fork
,另一个则不调用。 要亲自查看这一点,请在两台计算机上运行此命令:这是 Ruby 用于在两台计算机上执行示例中的
pstree
的命令,并带有引号。 您应该在 32 位计算机上看到bash---pstree
,在另一台计算机上看到bash---sh---pstree
。所以现在我很好奇,是什么让你发现了这种差异,它是否导致了问题?
Ruby performs shell expansion when %x is used with a single argument (like you are doing).
Here's my guess as to what is going on:
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:
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 thesh
command on the different machines, one callsfork
, the other doesn't. To see this for yourself, run this command on both machines:This is the command that Ruby is using to execute
pstree
in the example with quotes on both machines. You should seebash---pstree
on the 32-bit machine andbash---sh---pstree
on the other one.So now I'm curious, what led you to discover this difference and is it causing a problem?
我通过开发一个具有一系列子进程(fork)的异步处理器工作来经历这种情况,并且当主进程位于前台并收到 SIGINT 时发生这种情况。
我运行:puts“结果是%(monster-delayed-job)”
并且输出只是:“结果是”
Andre中“陷阱”SIGINT
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 "
Andre