Ruby %x разветвляется на 64-разрядный Linux, но не на 32-разрядный, и только с определенным синтаксисом

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-разрядной.

Это было полезно?

Решение

Ruby выполняет расширение оболочки, когда %x используется с одним аргументом (как это делаете вы).

Вот мое предположение относительно того, что происходит:

Ruby сканирует команду, чтобы определить, есть ли какие-либо специальные символы, которые привели бы к необходимости выполнения расширения оболочки, если это так, он вызывает оболочку для этого.Во втором примере одинарных кавычек достаточно, чтобы заставить Ruby захотеть вызвать оболочку для выполнения расширения, отсюда и форк.В первом примере Ruby может определить, что расширение оболочки не требуется, поскольку команда не содержит специальных символов (после расширения переменной), следовательно, форка нет.Разница между двумя версиями, вероятно, связана с внутренним изменением в том, как ruby пытается определить, требуется ли расширение оболочки.Я получаю форк для второго примера на ruby 1.8.5 на 32-разрядной машине.

[ПРАВИТЬ]

Хорошо, я взглянул на исходный код ruby 1.8.4 и 1.8.6, и обе версии используют одни и те же критерии для определения того, следует ли вызывать оболочку для выполнения расширения оболочки, если в командной строке существует любой из следующих символов, оболочка будет вызвана при предоставлении одного аргумента для %x:

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

Ruby фактически вызывает оболочку в обоих случаях (в примере, который содержит кавычки), причина, по которой вы видите разные выходные данные из pstree это связано с различиями в sh команда на разных машинах, одна вызывает fork, другой - нет.Чтобы убедиться в этом самостоятельно, запустите эту команду на обеих машинах:

/bin/sh -c "pstree $$"

Это команда, которую Ruby использует для выполнения pstree в примере с кавычками на обеих машинах.Ты должен увидеть bash---pstree на 32-разрядной машине и bash---sh---pstree с другой стороны.

Итак, теперь мне любопытно, что заставило вас обнаружить это различие и вызывает ли оно проблему?

Другие советы

Я прошел через эту ситуацию, разработав асинхронную работу процессора, которая имеет ряд подпроцессов (fork), и это произошло, когда мастер был на переднем плане и получил SIGINT.

Я бегу:выводит "результат равен %(monster-delayed-job)".

и на выходе был только:"в результате получается "

  • Да, я использую СИГИНТ "ловушки" в главном

Андре

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top