簡體   English   中英

Ruby %x 在 64 位 Linux 上分叉,但不在 32 位,並且僅使用特定語法

[英]Ruby %x forks on 64-bit Linux, but not on 32, and only with specific syntax

這是一些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 上它在execve()之前調用了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 上得到了第二個例子的 fork。

[編輯]

好的,我查看了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---pstree bash---sh---pstree

所以現在我很好奇,是什么讓您發現了這種差異,它是否會導致問題?

我通過開發具有一系列子進程(fork)的異步處理器工作來解決這種情況,當主進程在前台並收到一個 SIGINT 時,它發生了。

我跑: puts “結果是 %(monster-delayed-job)”

並且輸出只是:“結果是”

  • 是的,我在 master 中“陷阱”了 SIGINT

安德烈

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM