Suche…


Einführung

Es gibt viele Möglichkeiten, mit dem Betriebssystem zu interagieren. In Ruby können Sie Shell- / Systembefehle oder Unterprozesse ausführen.

Bemerkungen

Exec:
Die Funktionalität von Exec ist sehr eingeschränkt, und wenn es ausgeführt wird, wird das Ruby-Programm beendet und der Befehl ausgeführt.

Der Systembefehl:
Der Systembefehl wird in einer Subshell ausgeführt, anstatt den aktuellen Prozess zu ersetzen, und gibt true oder nill zurück. Der Systembefehl ist wie Backticks eine Blockierungsoperation, bei der die Hauptanwendung wartet, bis das Ergebnis der Systemoperation abgeschlossen ist. Hier muss sich der Hauptvorgang nie darum kümmern, eine vom untergeordneten Prozess ausgelöste Ausnahme zu erfassen.

Die Ausgabe der Systemfunktion ist immer wahr oder null, je nachdem, ob das Skript fehlerfrei ausgeführt wurde. Daher wird jeder Fehler beim Ausführen des Skripts nicht an unsere Anwendung weitergeleitet. Die Hauptoperation muss sich nie darum kümmern, eine vom untergeordneten Prozess ausgelöste Ausnahme zu erfassen. In diesem Fall ist die Ausgabe gleich Null, da der untergeordnete Prozess eine Ausnahme ausgelöst hat.
Dies ist eine Blockierungsoperation, bei der das Ruby-Programm wartet, bis die Operation des Befehls abgeschlossen ist, bevor es fortfährt.
Die Systemoperation verwendet Fork, um den aktuellen Prozess zu verzweigen und dann die angegebene Operation mit exec auszuführen.

Die Backticks (`):
Das Backtick-Zeichen befindet sich normalerweise unter der Escape-Taste auf der Tastatur. Backticks wird in einer Sub-Shell ausgeführt, anstatt den aktuellen Prozess zu ersetzen, und gibt das Ergebnis des Befehls zurück.
Hier können wir die Ausgabe des Befehls erhalten, aber das Programm stürzt ab, wenn eine Ausnahme generiert wird.
Wenn im Unterprozess eine Ausnahme vorhanden ist, wird diese Ausnahme an den Hauptprozess übergeben, und der Hauptprozess wird möglicherweise beendet, wenn die Ausnahme nicht behandelt wird. Dies ist eine Blockierungsoperation, bei der das Ruby-Programm wartet, bis die Operation des Befehls abgeschlossen ist, bevor es fortfährt.
Die Systemoperation verwendet Fork, um den aktuellen Prozess zu verzweigen und dann die angegebene Operation mit exec auszuführen.

IO.popen:
IO.popen wird in einem Unterprozess ausgeführt. Hier werden der Subprozess Standard Input und Standard Output mit dem IO-Objekt verbunden.

Popen3:
Mit Popen3 können Sie auf die Standardeingabe, Standardausgabe und Standardfehler zugreifen.
Die Standardeingabe und -ausgabe des Unterprozesses wird in IO-Objekte zurückgegeben.

$? (wie $ CHILD_STATUS)
Kann mit den Backticks, system () oder% x {} verwendet werden und gibt den Status des zuletzt ausgeführten Befehls an.
Dies kann nützlich sein, um auf den exitstatus und die pid Eigenschaften zuzugreifen.

$?.exitstatus

Empfohlene Methoden zum Ausführen von Shell-Code in Ruby:

Open3.popen3 oder Open3.capture3:
Open3 verwendet nur den Spawn-Befehl von Ruby, bietet jedoch eine viel bessere API.

Open3.popen3

Popen3 läuft in einem Unterprozess und gibt stdin, stdout, stderr und wait_thr zurück.

require 'open3'
stdin, stdout, stderr, wait_thr = Open3.popen3("sleep 5s && ls")
puts "#{stdout.read} #{stderr.read} #{wait_thr.value.exitstatus}"

oder

require 'open3'
cmd = 'git push heroku master'
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
  puts "stdout is:" + stdout.read
  puts "stderr is:" + stderr.read
end

wird ausgegeben: stdout ist: stderr ist: fatal: Kein git-Repository (oder eines der übergeordneten Verzeichnisse): .git

oder

require 'open3'
cmd = 'ping www.google.com'
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
  while line = stdout.gets
    puts line
  end
end

wird ausgeben:

Pinging von www.google.com [216.58.223.36] mit 32 Byte Daten:
Antwort von 216.58.223.36: Bytes = 32 Zeit = 16 ms TTL = 54
Antwort von 216.58.223.36: Bytes = 32 Zeit = 10 ms TTL = 54
Antwort von 216.58.223.36: Bytes = 32 Zeit = 21 ms TTL = 54
Antwort von 216.58.223.36: Bytes = 32 Zeit = 29 ms TTL = 54
Ping-Statistik für 216.58.223.36:
Pakete: Gesendet = 4, erhalten = 4, verloren = 0 (0% Verlust),
Ungefähre Umlaufzeiten in Millisekunden:
Minimum = 10 ms, Maximum = 29 ms, Durchschnitt = 19 ms


Open3.capture3:

require 'open3'

stdout, stderr, status = Open3.capture3('my_funky_command', 'and', 'some', 'argumants')
if status.success?
  # command completed successfully, do some more stuff
else
  raise "An error occured"
end

oder

Open3.capture3('/some/binary with some args')  

Aufgrund des zusätzlichen Aufwandes und der Möglichkeit von Shell-Injektionen jedoch nicht zu empfehlen.

Wenn der Befehl aus stdin liest und Sie einige Daten einspeisen möchten:

Open3.capture3('my_funky_command', stdin_data: 'read from stdin')  

Führen Sie den Befehl mit einem anderen Arbeitsverzeichnis aus, indem Sie chdir verwenden:

Open3.capture3('my_funky_command', chdir: '/some/directory')  

Klassische Methoden zum Ausführen von Shell-Code in Ruby:

Exec:

exec 'echo "hello world"'

oder

exec ('echo "hello world"')

Der Systembefehl:

system 'echo "hello world"'

Gibt "Hallo Welt" im Befehlsfenster aus.

oder

system ('echo "hello world"')

Der Systembefehl kann den Wert true zurückgeben, wenn der Befehl erfolgreich war oder nicht, wenn dies nicht der Fall war.

result = system 'echo "hello world"'
puts result  # will return a true in the command window

Die Backticks (`):

echo "hello world" Gibt "Hallo Welt" im Befehlsfenster aus.

Sie können das Ergebnis auch einfangen.

result = `echo "hello world"`  
puts "We always code a " + result  

IO.popen:

# Will get and return the current date from the system
IO.popen("date") { |f| puts f.gets }


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow