2010-07-01 9 views
76

Gibt es eine Möglichkeit, Befehlszeilenbefehle über Ruby auszuführen? Ich versuche, ein kleines kleines Ruby-Programm zu erstellen, das über Kommandozeilenprogramme wie 'screen', 'rcsz' usw. raustelefoniert und sendet.Ausführen von Befehlszeilenbefehlen in Ruby-Skript

Es wäre großartig, wenn ich das alles mit einbinden könnte Ruby (MySQL-Backend usw.)

Antwort

13

Es gibt einige Möglichkeiten, Systembefehle in Ruby auszuführen.

irb(main):003:0> `date /t` # surround with backticks 
=> "Thu 07/01/2010 \n" 
irb(main):004:0> system("date /t") # system command (returns true/false) 
Thu 07/01/2010 
=> true 
irb(main):005:0> %x{date /t} # %x{} wrapper 
=> "Thu 07/01/2010 \n" 

Aber wenn Sie tatsächlich benötigen, um Eingang und Ausgang mit dem stdin/stdout Befehl ausführen, werden Sie wahrscheinlich wollen am IO::popen Methode suchen, die speziell diese Anlage bietet.

+0

Popen auch nur Standard hat, wenn Ihre Anwendung funktioniert. Wenn Sie mehr Interaktion benötigen oder mit stdout, stdin und besonders stderr etwas anderes machen wollen, sollten Sie auch in open3 nachsehen: http://ruby-doc.org/core/classes/Open3.html –

180

Ja. Es gibt mehrere Möglichkeiten:


a. Verwenden %x oder ‚`‘:

%x(echo hi) #=> "hi\n" 
%x(echo hi >&2) #=> "" (prints 'hi' to stderr) 

`echo hi` #=> "hi\n" 
`echo hi >&2` #=> "" (prints 'hi' to stderr) 

Diese Methoden werden die stdout zurück und stderr an das Programm des leiten.


b. Verwendung system:

system 'echo hi' #=> true (prints 'hi') 
system 'echo hi >&2' #=> true (prints 'hi' to stderr) 
system 'exit 1' #=> nil 

Diese Methode liefert true, wenn der Befehl erfolgreich war. Es leitet alle Ausgaben an die Programme um.


c. Verwendung exec:

fork { exec 'sleep 60' } # you see a new process in top, "sleep", but no extra ruby process. 
exec 'echo hi' # prints 'hi' 
# the code will never get here. 

, dass der aktuelle Prozess mit dem durch den Befehl erstellt ersetzt.


d. (Rubin 1.9) verwendet spawn:

spawn 'sleep 1; echo one' #=> 430 
spawn 'echo two' #=> 431 
sleep 2 
# This program will print "two\none". 

Diese Methode ist nicht für den Prozess zu beenden nicht warten, und gibt die PID.


e. Verwenden IO.popen:

io = IO.popen 'cat', 'r+' 
$stdout = io 
puts 'hi' 
$stdout = IO.new 0 
p io.read(1) 
io.close 
# prints '"h"'. 

Diese Methode wird ein IO Objekt zurück, das die neuen Prozesse Eingabe/Ausgabe reperesents. Es ist derzeit auch die einzige mir bekannte Art, dem Programm Input zu geben.


f. Verwenden Sie Open3 (am 1.9.2 und höher)

require 'open3' 

stdout,stderr,status = Open3.capture3(some_command) 
STDERR.puts stderr 
if status.successful? 
    puts stdout 
else 
    STDERR.puts "OH NO!" 
end 

Open3 hat mehrere andere Funktionen für expliziten Zugriff auf die beiden Ausgangsströme zu bekommen. Es ist vergleichbar mit popen, gibt Ihnen aber Zugriff auf stderr.

+0

Brilliant summary Adrian Danke für das Teilen dieser Informationen. – KomodoDave

+0

Bonustrick: 'io = IO.popen 'cat> out.log', 'r +''; schreibt die Ausgaben des Befehls in "out.log" – Narfanator

+1

Was sind die Vor- und Nachteile für jeden. Wie entscheide ich, was ich benutzen soll? Wie wäre es mit 'FileUtils' [http://ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html]? – Ava

2

Ja, das ist sicherlich machbar, aber die Methode der Implementierung unterscheidet sich abhängig davon, ob das betreffende "Befehlszeilen" -Programm im "Vollbild" - oder Befehlszeilenmodus arbeitet. Programme, die für die Befehlszeile geschrieben werden, neigen dazu, STDIN zu lesen und in STDOUT zu schreiben. Diese können direkt in Ruby mit den Standard-Backtick-Methoden und/oder System/Exec-Aufrufen aufgerufen werden.

Wenn das Programm im "Vollbild" -Modus wie Bildschirm oder vi arbeitet, muss der Ansatz anders sein. Für Programme wie diese sollten Sie nach einer Ruby-Implementierung der "expect" -Bibliothek suchen. Dadurch können Sie scripten, was Sie auf dem Bildschirm erwarten und was Sie senden müssen, wenn Sie diese speziellen Zeichenfolgen auf dem Bildschirm sehen.

Dies ist wahrscheinlich nicht der beste Ansatz, und Sie sollten sich wahrscheinlich anschauen, was Sie zu erreichen versuchen und die entsprechende Bibliothek/das entsprechende Juwel finden, anstatt eine vorhandene Vollbildanwendung zu automatisieren. Als Beispiel behandelt "Need assistance with serial port communications in Ruby" die Kommunikation über serielle Schnittstelle, einen Vorläufer zum Wählen, wenn dies mit den von Ihnen erwähnten spezifischen Programmen erreicht werden soll.

+0

Eine einfache Version von Expect ist in Ruby mit seinem eingebauten [Pty] (http://www.ruby-doc.org/stdlib-1.9.3/libdoc/pty/rdoc/PTY.html) Modul verfügbar . –

6
folder = "/" 
list_all_files = "ls -al #{folder}" 
output = `#{list_all_files}` 
puts output 
0

die am häufigsten verwendete Methode Open3 hier verwendet, ist meine Code-Version des obigen Codes mit einigen Korrekturen bearbeitet:

require 'open3' 
puts"Enter the command for execution" 
some_command=gets 
stdout,stderr,status = Open3.capture3(some_command) 
STDERR.puts stderr 
if status.success? 
    puts stdout 
else 
    STDERR.puts "ERRRR" 
end