Shell-Befehle von Ruby aus aufrufen

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

    06 March 2015
    Andrew Marshallrickyduck
19 answers
  • Diese Erklärung basiert auf einem kommentierten Ruby-Skript von einem Freund von mir. Wenn Sie das Skript verbessern möchten, können Sie es unter dem Link aktualisieren.

    Beachten Sie, dass wenn Ruby eine Shell anruft, normalerweise /bin/sh, nicht Bash. Einige Bash-Syntax wird von /bin/sh nicht auf allen Systemen unterstützt.

    Hier können Sie ein Shellskript ausführen:

     [pre> cmd = "echo 'hi'" # Sample string that can be used
     
    1. Kernel#`, allgemein als Backticks bezeichnet ? `cmd`

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

      Gibt das Ergebnis 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 )

      Dem Zeichen x folgt ein Trennzeichen, das ein beliebiges Zeichen sein kann. Wenn das Trennzeichen eines der Zeichen ( ist, [, { oder <, Das Literal besteht aus den Zeichen bis zum passenden abschließenden Trennzeichen. Berücksichtigt dabei geschachtelte Trennzeichenpaare. Bei allen anderen Trennzeichen umfasst das Literal die Zeichen bis zum nächsten Vorkommen des Trennzeichens . String-Interpolation #{ ... } ist zulässig.

      Gibt das Ergebnis des Shell-Befehls genauso wie die Backticks zurück.

      Docs: http://www.ruby-doc.org/docs/ProgrammingRuby/html /language.html

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

      Führt den angegebenen Befehl in einer Subshell aus.

      Gibt true zurück, wenn der Befehl erfolgreich gefunden wurde und ausgeführt wurde, andernfalls false.

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

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

      18 August 2016
      the Tin ManEqbal
  • Ich mache das gerne mit dem Literal %x, was die Verwendung von Anführungszeichen in einem Befehl einfach (und lesbar!) macht:

     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
     
    10 January 2013
    Andrew Marshallrickyduck
  • Hier ist der beste Artikel meiner Meinung über das Ausführen von Shell-Skripten in Ruby: " 6 Möglichkeiten, Shell-Befehle in Ruby auszuführen ".

    Wenn Sie nur die Ausgabe benötigen, verwenden Sie Backticks.

    Ich brauchte fortgeschrittenere Sachen wie STDOUT und STDERR, also habe ich den Open4-Edelstein verwendet. Sie haben dort alle Methoden erklärt.

    11 October 2013
    the Tin ManEqbal
  • Mein Favorit ist Open3

       require "open3"
    
      Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }
     
    13 July 2012
    DManEthan Hinson
  • Wenn Sie zwischen diesen Mechanismen wählen, sollten Sie einige Überlegungen anstellen:

    1. Wollen Sie nur stdout oder brauchen Sie stderr auch? oder sogar getrennt?
    2. Wie groß ist Ihre Ausgabe? Möchten Sie, dass das gesamte Ergebnis im Speicher hält?
    3. Möchten Sie einen Teil Ihrer -Ausgabe lesen, während der Unterprozess noch ausgeführt wird?
    4. Benötigen Sie Ergebniscodes?
    5. Benötigen Sie ein Ruby-Objekt, das den Prozess darstellt und Sie ihn bei Bedarf beenden kann?

    Möglicherweise benötigen Sie alles von einfachen Backticks (``), system () und IO.popen bis zu vollständigem Kernel.fork / Kernel.exec mit IO.pipe und IO.select.

    Sie können auch Zeitüberschreitungen in den Mix einplanen, wenn die Ausführung eines Unterprozesses zu lange dauert.

    Leider hängt es sehr stark von ab .

    11 October 2013
    the Tin ManEqbal
  • Eine weitere Option:

    Wenn Sie:

    • benötigen Sie auch stderr stdout
    • kann / kann Open3 / Open4 nicht verwenden (sie werfen auf meinem Mac Ausnahmen in NetBeans aus, keine Ahnung warum)

    Sie können die Shell-Umleitung verwenden:

     puts %x[cat bogus.txt].inspect
      => ""
    
    puts %x[cat bogus.txt 2>&1].inspect
      => "cat: bogus.txt: No such file or directory\n"
     

    Die Syntax 2>&1 funktioniert in Linux , Mac und Windows seit den Anfängen von MS-DOS.

    11 October 2013
    the Tin ManEqbal
  • Ich bin definitiv kein Ruby-Experte, aber ich versuche es:

     $ irb 
    system "echo Hi"
    Hi
    => true
     

    Sie sollten auch in der Lage sein, Folgendes zu tun:

     cmd = 'ls'
    system(cmd)
     
    11 October 2013
    the Tin ManEqbal
  • Die obigen Antworten sind bereits großartig, aber ich möchte den folgenden zusammenfassenden Artikel wirklich teilen: " 6 Möglichkeiten, Shell-Befehle in Ruby auszuführen "

    Grundsätzlich heißt es:

    <|

    Kernel#exec:

     exec 'echo "hello $HOSTNAME"'
     

    system und $?:

     system 'false' 
    puts $?
     

    Backticks (`):

     today = `date`
     

    IO#popen:

     IO.popen("date") { |f| puts f.gets }
     

    Open3#popen3 - stdlib:

     require "open3"
    stdin, stdout, stderr = Open3.popen3('dc') 
     

    Open4#popen4 - ein Juwel:

     require "open4" 
    pid, stdin, stdout, stderr = Open4::popen4 "false" # => [26327, #<IO:0x6dff24>, #<IO:0x6dfee8>, #<IO:0x6dfe84>]
     
    07 February 2017
    not a patchPradeep Sapkota
  • Wenn Sie Bash wirklich benötigen, beachten Sie die Anmerkung in der Antwort "Beste".

    Beachten Sie zuerst, wann Ruby anruft Bei einer Shell werden normalerweise /bin/sh, nicht Bash aufgerufen. Einige Bash-Syntax wird von /bin/sh nicht auf allen Systemen unterstützt.

    Wenn Sie Bash verwenden müssen, fügen Sie bash -c "your Bash-only command" in die gewünschte Aufrufmethode ein.

    quick_output = system("ls -la")

    quick_bash = system("bash -c 'ls -la'")

    So testen Sie:

    system("echo $SHELL") system('bash -c "echo $SHELL"')

    Oder wenn Sie eine vorhandene Skriptdatei ausführen (z. B. script_output = system("./my_script.sh")), sollte Ruby den Shebang beachten, aber Sie könnten immer [&&7 && verwenden. ], um sicherzugehen (obwohl es bei /bin/sh bei laufendem /bin/bash zu einem geringfügigen Mehraufwand kommen kann, bemerken Sie dies wahrscheinlich nicht.

    02 June 2017
    dragon788
  • Sie können auch die Backtick-Operatoren (`) verwenden, ähnlich wie Perl:

     directoryListing = `ls /`
    puts directoryListing # prints the contents of the root directory
     

    Praktisch, wenn Sie etwas einfaches brauchen.

    Welche Methode Sie verwenden möchten, hängt davon ab, was genau Sie erreichen möchten. Weitere Informationen zu den verschiedenen Methoden finden Sie in den Dokumenten.

    05 August 2008
    Rufo Sanchez