325 votes

Obtenir la sortie des appels système () en Ruby

Si j’appelle une commande à l’aide de `` en Ruby, comment faire sa sortie ?

362voto

Craig Walker Points 13478

Je voudrais élargir et préciser la réponse de chaos un peu.

Si vous entourent votre commande avec apostrophes inverses, alors vous n’avez pas besoin d’appeler (explicitement) system() du tout. Les apostrophes inverses, exécutez la commande et renvoyer le résultat sous forme de chaîne. Vous pouvez ensuite assigner la valeur à une variable comme suit :

246voto

Simon Hürlimann Points 1533

Sachez que toutes les solutions où vous passez une chaîne de caractères contenant de l'utilisateur fourni des valeurs de system, %x[] etc. sont dangereux! Dangereux signifie en réalité: l'utilisateur peut déclencher l'exécution de code dans le contexte et avec toutes les autorisations de programme.

Aussi loin que je peux dire qu' system et Open3.popen3 faire sécuriser/échapper à la variante en Ruby 1.8. En Ruby 1.9 IO::popen accepte également un tableau.

Simplement passer chaque option et en argument un tableau à l'un de ces appels.

Si vous avez besoin non seulement le statut de sortie, mais aussi le résultat vous voudrez probablement utiliser Open3.popen3:

require 'open3'
stdin, stdout, stderr, wait_thr = Open3.popen3('usermod', '-p', @options['shadow'], @options['username'])
stdout.gets(nil)
stderr.gets(nil)
exit_code = wait_thr.value

Notez que le bloc de formulaire de fermeture automatique de stdin, stdout et stderr - sinon, ils doivent être fermés explicitement.

Plus d'informations ici: Formant sanitaires ou des commandes shell du système d'appels en Ruby

174voto

FernandoFabreti Points 1087

Juste pour mémoire, si vous voulez les deux (résultat de sortie et opération), vous pouvez faire :

76voto

Denis Points 34131

La façon simple de le faire correctement et en toute sécurité est d'utiliser Open3.capture2(), Open3.capture2e()ou Open3.capture3().

À l'aide de ruby backticks et son %x alias sont PAS sécurisés. Il est DANGEREUX. Lors de l'utilisation de, échapper au non fiables des données de la même manière que dans un shell:

untrusted = "foo; echo 'rm -rf *'"
out = `echo #{untrusted}`                              # BAD
out = `echo "#{untrusted}"`                            # good

L' system de la fonction, en revanche, s'échappe arguments correctement si elle est utilisée correctement:

ret = system "echo #{untrusted}"                       # BAD
ret = system 'echo', untrusted                         # good

La difficulté est, il renvoie le code de sortie au lieu de la sortie, et la capture de ce dernier est compliqué et désordonné.

La meilleure réponse dans ce fil jusqu'à présent mentionne Open3, mais pas les fonctions qui sont le mieux à la tâche. Open3.capture2, capture2e et capture3 travail comme system, mais retourne deux ou trois arguments:

out, err, st = Open3.capture3("echo #{untrusted}")     # BAD
out, err, st = Open3.capture3('echo', untrusted)       # good
out_err, st  = Open3.capture2e('echo', untrusted)      # good
out, st      = Open3.capture2('echo', untrusted)       # good
p st.exitstatus

Un autre mentionne IO.popen(). La syntaxe peut être maladroit dans le sens qu'il veut un tableau en entrée, mais il fonctionne aussi:

out = IO.popen(['echo', untrusted]).read               # good

Pour plus de commodité, vous pouvez envelopper Open3.capture3() dans une fonction, par exemple:

#
# Returns stdout on success, false on failure, nil on error
#
def syscall(*cmd)
  begin
    stdout, stderr, status = Open3.capture3(*cmd)
    status.success? && stdout.slice!(0..-(1 + $/.size)) # strip trailing eol
  rescue
  end
end

Exemple:

p system('foo')
p syscall('foo')
p system('which', 'foo')
p syscall('which', 'foo')
p system('which', 'which')
p syscall('which', 'which')

Les rendements suivants:

nil
nil
false
false
/usr/bin/which         <- stdout from system('which', 'which')
true                   <- p system('which', 'which')
"/usr/bin/which"       <- p syscall('which', 'which')

62voto

Martin Gross Points 663

Vous pouvez utiliser [] System () ou x %, en fonction de quel genre de résultat dont vous avez besoin.

System() retournant true si la commande a été trouvée et a couru avec succès, false sinon.

%x [..] enregistre en revanche les résultats de la commande sous forme de chaîne :

E blog post par Jay champs explique en détail les différences entre l’utilisation de système, exec et %x [..].

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X