1265 Stimmen

Wie man Shell-Befehle aus Ruby aufruft

Wie kann ich Shell-Befehle aus einem Ruby-Programm heraus aufrufen? Wie bekomme ich dann die Ausgabe dieser Befehle zurück in Ruby?

4 Stimmen

Diese Frage ist zwar nützlich, aber sie wird nicht gut gestellt. Ruby hat viele Möglichkeiten, Sub-Shells aufzurufen, die gut dokumentiert sind und leicht durch Lesen der Kernel y Öffnen3 Dokumentation und Suche hier auf SO.

3 Stimmen

Leider ist dieses Thema sehr komplex. Open3 ( docs ) ist die beste Wahl für die meisten Situationen, IMO, aber auf älteren Versionen von Ruby, wird es nicht respektieren eine modifizierte PATH ( bugs.ruby-lang.org/issues/8004 ), und je nachdem, wie Sie args übergeben (insbesondere, wenn Sie opts hash mit Nicht-Schlüsselwörtern verwenden), kann es zu einem Bruch kommen. Aber, wenn Sie diese Situationen treffen, dann tun Sie etwas ziemlich fortgeschritten und Sie können herausfinden, was zu tun ist, indem Sie die Implementierung von Open3 .

6 Stimmen

Ich bin überrascht, dass niemand erwähnt hat Shellwords.escape ( doc ). Sie möchten keine Benutzereingaben direkt in Shell-Befehle einfügen - geben Sie sie zuerst in einer Escape-Funktion ein! Siehe auch Befehlsinjektion .

1474voto

Steve Willard Punkte 16337

Diese Erklärung stützt sich auf eine kommentierte Ruby-Skript von einem Freund von mir. Wenn Sie das Skript verbessern möchten, können Sie es über den Link aktualisieren.

Zunächst ist zu beachten, dass Ruby bei Aufrufen einer Shell typischerweise /bin/sh , no Bash. Einige Bash-Syntaxen werden nicht unterstützt von /bin/sh auf allen Systemen.

Hier finden Sie Möglichkeiten zur Ausführung eines Shell-Skripts:

cmd = "echo 'hi'" # Sample string that can be used
  1. Kernel#` gemeinhin Backticks genannt - `cmd`

    Das ist wie bei vielen anderen Sprachen, einschließlich Bash, PHP und Perl.

    Gibt das Ergebnis (d.h. die Standardausgabe) des Shell-Befehls zurück.

    Dokumente: http://ruby-doc.org/core/Kernel.html#method-i-60

    value = `echo 'hi'`
    value = `#{cmd}`
  2. Eingebaute Syntax, %x( cmd )

    Nach der x Zeichen ist ein Begrenzungszeichen, das ein beliebiges Zeichen sein kann. Wenn das Begrenzungszeichen eines der folgenden Zeichen ist ( , [ , { , oder < , besteht das Literal aus den Zeichen bis zum passenden schließenden Begrenzer, wobei verschachtelte Begrenzungszeichenpaare berücksichtigt werden. Bei allen anderen Begrenzungszeichen besteht das Literal aus den Zeichen bis zum nächsten Vorkommen des Begrenzungszeichens. Interpolation von Zeichenketten #{ ... } ist erlaubt.

    Gibt das Ergebnis (d.h. die Standardausgabe) des Shell-Befehls zurück, genau wie die Backticks.

    Dokumente: https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-Percent+Saiten

    value = %x( echo 'hi' )
    value = %x[ #{cmd} ]
  3. Kernel#system

    Führt den angegebenen Befehl in einer Subshell aus.

    Rückgabe true wenn der Befehl gefunden und erfolgreich ausgeführt wurde, false sonst.

    Dokumente: http://ruby-doc.org/core/Kernel.html#method-i-system

    wasGood = system( "echo 'hi'" )
    wasGood = system( cmd )
  4. Kernel#exec

    Ersetzt den aktuellen Prozess durch die Ausführung des angegebenen externen Befehls.

    Wird kein Wert zurückgegeben, wird der aktuelle Prozess ersetzt und nicht fortgesetzt.

    Dokumente: http://ruby-doc.org/core/Kernel.html#method-i-exec

    exec( "echo 'hi'" )
    exec( cmd ) # Note: this will never be reached because of the line above

Hier noch ein paar zusätzliche Ratschläge: $? , was dasselbe ist wie $CHILD_STATUS greift auf den Status des zuletzt vom System ausgeführten Befehls zu, wenn Sie die Backticks verwenden, system() o %x{} . Sie können dann auf die exitstatus y pid Eigenschaften:

$?.exitstatus

Für weitere Informationen siehe:

404voto

Ian Punkte 10246

167voto

cynicalman Punkte 5781

Ich verwende dazu am liebsten die Methode %x Literal, das es einfach (und lesbar!) macht, Anführungszeichen in einem Befehl zu verwenden, etwa so:

directorylist = %x[find . -name '*test.rb' | sort]

In diesem Fall wird die Dateiliste mit allen Testdateien im aktuellen Verzeichnis gefüllt, die Sie wie erwartet verarbeiten können:

directorylist.each do |filename|
  filename.chomp!
  # work with file
end

68voto

Mihai A Punkte 1461

Hier ist der meiner Meinung nach beste Artikel über das Ausführen von Shell-Skripten in Ruby: " 6 Möglichkeiten, Shell-Befehle in Ruby auszuführen ".

Wenn Sie nur die Ausgabe erhalten möchten, verwenden Sie Backticks.

Ich brauchte fortgeschrittenere Dinge wie STDOUT und STDERR, also habe ich das Open4-Gem verwendet. Dort sind alle Methoden erklärt.

46voto

anshul Punkte 5897

Mein Favorit ist Öffnen3

  require "open3"

  Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X