Ruby% x se bifurca en Linux de 64 bits, pero no en 32, y solo con sintaxis específica

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

  •  03-07-2019
  •  | 
  •  

Pregunta

Aquí hay un código Ruby:

puts %x{ pstree #{$} }   # never forks
puts %x{ pstree '#{$}' } # forks on amd64 only

En Ubuntu Dapper de 32 bits, obtengo esta salida:

t.rb---pstree
t.rb---pstree

Lo que tiene sentido para mí. Pero en Ubuntu Hardy de 64 bits, obtengo esto:

t.rb---sh---pstree
t.rb---pstree

Lo que se muestra aquí es que Ruby se bifurca antes de ejecutar solo en uno de los casos. Cuando coloco el código en un archivo y lo ejecuto bajo strace -f, parece que en Hardy de 64 bits llama a clone () (como fork () ) antes de execve () , mientras que en Dapper de 32 bits no hace tal cosa.

Mis versiones de Ruby son:

ruby 1.8.4 (2005-12-24) [i486-linux]
ruby 1.8.6 (2007-09-24 patchlevel 111) [x86_64-linux]

Debería intentar mezclar & amp; intérpretes a juego & amp; SO y amp; el tamaño de las palabras es mayor, pero en este momento no es fácil ya que no administro estas máquinas. Tal vez alguien entre ustedes pueda decirme cuál es la diferencia incluso entre estos comandos en el sistema de 64 bits, y mucho menos por qué funcionan de la misma manera en el de 32 bits.

¿Fue útil?

Solución

Ruby realiza la expansión de shell cuando se usa% x con un solo argumento (como lo está haciendo).

Esta es mi opinión sobre lo que está pasando:

Ruby escanea el comando para determinar si hay algún carácter especial que resulte en la necesidad de realizar una expansión de shell, si es así, llama al shell a hacerlo. En el segundo ejemplo, las comillas simples son suficientes para hacer que Ruby quiera llamar al shell para hacer la expansión, de ahí el tenedor. En el primer ejemplo, Ruby puede determinar que la expansión del shell no es necesaria ya que el comando no contiene caracteres especiales (después de la expansión de la variable), por lo tanto, no hay bifurcación. La diferencia entre las dos versiones probablemente tiene que ver con un cambio interno en la forma en que Ruby intenta determinar si se necesita la expansión de shell. Obtengo un tenedor para el segundo ejemplo en ruby ??1.8.5 en una máquina de 32 bits.

[EDITAR]

De acuerdo, eché un vistazo al código fuente de ruby ??1.8.4 y 1.8.6 y ambas versiones usan los mismos criterios para determinar si llamar o no a un shell para realizar una expansión de shell, si existe alguno de los siguientes caracteres en la línea de comandos se invocará el shell cuando se proporcione un argumento para% x:

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

Ruby está llamando al shell en ambos casos (en el ejemplo que contiene las comillas), la razón por la que está viendo diferentes salidas de pstree se debe a las diferencias en el sh comando en las diferentes máquinas, uno llama fork , el otro no. Para ver esto por ti mismo, ejecuta este comando en ambas máquinas:

/bin/sh -c "pstree $"

Este es el comando que Ruby está utilizando para ejecutar pstree en el ejemplo con comillas en ambas máquinas. Debería ver bash --- pstree en la máquina de 32 bits y bash --- sh --- pstree en la otra.

Así que ahora tengo curiosidad, ¿qué te llevó a descubrir esta diferencia y está causando un problema?

Otros consejos

Pasé por esta situación desarrollando un trabajo de procesador asíncrono que tiene una serie de subprocesos (fork), y sucedió cuando el maestro estaba en primer plano y recibió un SIGINT.

Ejecuto: pone " el resultado es% (monster-delayed-job) "

y la salida fue solo: " el resultado es "

  • Sí, Im " trampa " SIGINT en el maestro

Andre

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top