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 位系统上工作相同了。
解决方案
当%x与单个参数一起使用时,Ruby会执行shell扩展(就像你正在做的那样)。
以下是关于发生了什么的猜测:
Ruby扫描命令以确定是否有任何特殊字符会导致需要执行shell扩展,如果是这样,它会调用shell来执行此操作。在第二个例子中,单引号足以让Ruby想要调用shell来进行扩展,因此fork。在第一个例子中,Ruby可以确定不需要shell扩展,因为命令不包含特殊字符(在变量扩展之后),因此没有fork。两个版本之间的差异可能与ruby试图确定shell扩展需要的内部更改有关。我在32位机器上的ruby 1.8.5上得到了第二个例子。
[编辑]
好的,我查看了ruby 1.8.4和1.8.6的源代码,如果存在以下任何字符,两个版本都使用相同的标准来确定是否调用shell来执行shell扩展在命令行中,当提供%x的一个参数时,将调用shell:
*?{}[]<>()~&|\\$;'`"\n
Ruby实际上是在两种情况下都调用shell(在包含引号的示例中),你看到来自 pstree
的不同输出的原因是由于 sh的差异代码>命令在不同的机器上,一个调用
fork
,另一个不调用。要自己查看,请在两台计算机上运行此命令:
/bin/sh -c "pstree $"
这是Ruby用于在两个机器上的引号中执行 pstree
的命令。你应该在32位机器上看到 bash --- pstree
,在另一台机器上看到 bash --- sh --- pstree
。
所以现在我很好奇,是什么导致你发现这种差异并导致问题?
其他提示
我通过开发一个具有一系列子进程(fork)的异步处理器工作来经历这种情况,并且当主进程位于前台并收到 SIGINT 时发生这种情况。
我跑:提出“结果是%(怪物延迟工作)”
输出只有:“结果是”
- 是的,我在主站中“捕获”SIGINT
安德烈