Ruby %x 在 64 位 Linux 上分叉,但不在 32 位 Linux 上分叉,并且仅使用特定语法

StackOverflow https://stackoverflow.com/questions/214205

  •  03-07-2019
  •  | 
  •  

这是一些 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

安德烈

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top