Wenn ich einen Befehl aufrufe mit Kernel#System in Ruby, wie erhalte ich die Ausgabe?
system("ls")
Wenn ich einen Befehl aufrufe mit Kernel#System in Ruby, wie erhalte ich die Ausgabe?
system("ls")
Ich möchte das Thema erweitern und präzisieren Die Antwort des Chaos ein wenig.
Wenn Sie Ihren Befehl mit Backticks umgeben, müssen Sie system() gar nicht (explizit) aufrufen. Die Backticks führen den Befehl aus und geben die Ausgabe als String zurück. Sie können den Wert dann wie folgt einer Variablen zuweisen:
output = `ls`
p output
o
printf output # escapes newline chars
Beachten Sie, dass alle Lösungen, bei denen Sie eine Zeichenkette mit benutzerdefinierten Werten an system
, %x[]
usw. sind unsicher! Unsicher bedeutet eigentlich: Der Benutzer darf Code im Kontext und mit allen Rechten des Programms zur Ausführung bringen.
Soweit ich sagen kann, nur system
y Open3.popen3
bieten in Ruby 1.8 eine Secure/Escaping-Variante. In Ruby 1.9 IO::popen
akzeptiert auch ein Array.
Übergeben Sie einfach jede Option und jedes Argument als Array an einen dieser Aufrufe.
Wenn Sie nicht nur den Exit-Status, sondern auch das Ergebnis benötigen, sollten Sie wahrscheinlich Open3.popen3
:
require 'open3'
stdin, stdout, stderr, wait_thr = Open3.popen3('usermod', '-p', @options['shadow'], @options['username'])
stdout.gets(nil)
stdout.close
stderr.gets(nil)
stderr.close
exit_code = wait_thr.value
Beachten Sie, dass die Blockform stdin, stdout und stderr automatisch schließt - andernfalls müssten sie in ausdrücklich geschlossen .
Weitere Informationen finden Sie hier: Synthetische Shell-Befehle oder Systemaufrufe in Ruby formulieren
Der einfachste Weg, dies korrekt und sicher zu tun, ist die Verwendung von Open3.capture2()
, Open3.capture2e()
, oder Open3.capture3()
.
Mit den Backticks von Ruby und seiner %x
Alias sind UNTER KEINEN UMSTÄNDEN SICHER wenn sie mit nicht vertrauenswürdigen Daten verwendet werden. Es ist GEFÄHRLICH schlicht und einfach:
untrusted = "; date; echo"
out = `echo #{untrusted}` # BAD
untrusted = '"; date; echo"'
out = `echo "#{untrusted}"` # BAD
untrusted = "'; date; echo'"
out = `echo '#{untrusted}'` # BAD
En system
Funktion werden die Argumente dagegen korrekt umgangen bei richtiger Anwendung :
ret = system "echo #{untrusted}" # BAD
ret = system 'echo', untrusted # good
Das Problem ist, dass der Exit-Code anstelle der Ausgabe zurückgegeben wird, und die Erfassung des letzteren ist umständlich und unübersichtlich.
Die bisher beste Antwort in diesem Thread erwähnt zwar Open3, aber nicht die Funktionen, die für diese Aufgabe am besten geeignet sind. Open3.capture2
, capture2e
y capture3
arbeiten wie system
, gibt aber zwei oder drei Argumente zurück:
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
Eine weitere Erwähnung IO.popen()
. Die Syntax kann in dem Sinne ungeschickt sein, dass sie ein Array als Eingabe verlangt, aber sie funktioniert auch:
out = IO.popen(['echo', untrusted]).read # good
Der Einfachheit halber können Sie Folgendes einpacken Open3.capture3()
in einer Funktion, z.B.:
#
# 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
Beispiel:
p system('foo')
p syscall('foo')
p system('which', 'foo')
p syscall('which', 'foo')
p system('which', 'which')
p syscall('which', 'which')
Ergibt das Folgende:
nil
nil
false
false
/usr/bin/which <— stdout from system('which', 'which')
true <- p system('which', 'which')
"/usr/bin/which" <- p syscall('which', 'which')
Sie können system() oder %x[] verwenden, je nachdem, welche Art von Ergebnis Sie benötigen.
system() liefert true, wenn der Befehl gefunden und erfolgreich ausgeführt wurde, andernfalls false.
>> s = system 'uptime'
10:56 up 3 days, 23:10, 2 users, load averages: 0.17 0.17 0.14
=> true
>> s.class
=> TrueClass
>> $?.class
=> Process::Status
%x[..] hingegen speichert die Ergebnisse des Befehls als Zeichenkette:
>> result = %x[uptime]
=> "13:16 up 4 days, 1:30, 2 users, load averages: 0.39 0.29 0.23\n"
>> p result
"13:16 up 4 days, 1:30, 2 users, load averages: 0.39 0.29 0.23\n"
>> result.class
=> String
Th Blogbeitrag von Jay Fields erklärt im Detail die Unterschiede zwischen der Verwendung von system, exec und %x[ ] .
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.