Ruby% x forks sur Linux 64 bits, mais pas sur 32, et uniquement avec une syntaxe spécifique

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

  •  03-07-2019
  •  | 
  •  

Question

Voici du code Ruby:

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

Sur Ubuntu Dapper 32 bits, je reçois cette sortie:

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

Ce qui a du sens pour moi. Mais sur Ubuntu Hardy 64 bits, je reçois ceci:

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

Ce qui est montré ici, c'est que Ruby se fourre avant d'exécuter dans un cas seulement. Lorsque je mets le code dans un fichier et que je l'exécute sous strace -fF, il apparaît que Hardy 64 bits appelle clone () (comme fork () ) avant execve () , alors que sur Dapper 32 bits, il ne fait rien de tel.

Mes versions de Ruby sont les suivantes:

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

Je devrais essayer de mélanger & amp; correspondant interprètes & amp; OS & amp; taille des mots plus, mais pour le moment ce n'est pas facile car je ne gère pas ces machines. Peut-être que quelqu'un parmi vous pourra me dire quelle est même la différence entre ces commandes sur le système 64 bits, sans parler de la raison pour laquelle elles fonctionnent de la même manière sur le système 32 bits.

Était-ce utile?

La solution

Ruby effectue une expansion du shell lorsque% x est utilisé avec un seul argument (comme vous le faites).

Voici ce que je pense de ce qui se passe:

Ruby analyse la commande pour déterminer s’il existe des caractères spéciaux qui nécessiteraient une expansion du shell, s’il le fait alors. Dans le deuxième exemple, les guillemets simples sont suffisants pour que Ruby veuille appeler le shell pour procéder à l'expansion, d'où le fork. Dans le premier exemple, Ruby peut déterminer que l'extension du shell n'est pas nécessaire, car la commande ne contient aucun caractère spécial (après l'extension variable), donc pas de fork. La différence entre les deux versions est probablement liée à un changement interne dans la façon dont Ruby essaie de déterminer si une expansion du shell est nécessaire. Je reçois un fork pour le deuxième exemple sur ruby ??1.8.5 sur une machine 32 bits.

[EDIT]

D'accord, j'ai jeté un coup d'œil au code source de ruby ??1.8.4 et 1.8.6 et les deux versions utilisent les mêmes critères pour déterminer s'il convient ou non d'appeler un shell pour effectuer une expansion du shell, si l'un des caractères suivants existe le shell sera invoqué dans la ligne de commande lorsqu'un seul argument à% x est fourni:

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

Ruby appelle en réalité le shell dans les deux cas (dans l'exemple qui contient les guillemets), la raison pour laquelle vous voyez des sorties différentes de pstree est due aux différences entre les sh sur les différentes machines, l’une appelle fork , l’autre ne le fait pas. Pour voir cela par vous-même, exécutez cette commande sur les deux machines:

/bin/sh -c "pstree $"

Il s’agit de la commande que Ruby utilise pour exécuter pstree dans l’exemple avec des guillemets sur les deux machines. Vous devriez voir bash --- pstree sur la machine 32 bits et bash --- sh --- pstree sur l'autre.

Alors maintenant, je suis curieux de savoir ce qui vous a amené à découvrir cette différence et est-ce que cela pose un problème?

Autres conseils

J'ai vécu cette situation en développant un travail de processeur asynchrone comportant une série de sous-processus (fork), et cela est arrivé lorsque le maître était au premier plan et a reçu un SIGINT.

J'exécute: met "le résultat est% (monster-retard-job)" "

et la sortie était uniquement: "le résultat est"

  • Oui, je "piège" SIGINT dans le maître

André

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top