Wie rufe ich einen Systembefehl in Rust auf und erfasse seine Ausgabe?

89

Gibt es eine Möglichkeit, einen Systembefehl wie lsoder fuserin Rust aufzurufen ? Wie wäre es mit der Erfassung der Ausgabe?

quux00
quelle

Antworten:

117

std::process::Command ermöglicht das.

Es gibt mehrere Möglichkeiten, einen untergeordneten Prozess zu erzeugen und einen beliebigen Befehl auf dem Computer auszuführen:

  • spawn - führt das Programm aus und gibt einen Wert mit Details zurück
  • output - führt das Programm aus und gibt die Ausgabe zurück
  • status - führt das Programm aus und gibt den Exit-Code zurück

Ein einfaches Beispiel aus den Dokumenten:

use std::process::Command;

Command::new("ls")
        .arg("-l")
        .arg("-a")
        .spawn()
        .expect("ls command failed to start");
Talles
quelle
2
Was ist, wenn ich Echtzeitausgabe erhalten muss? Ich denke, die outputFunktion gibt Vec nach Abschluss des Prozesses zurück. Also, falls wir so etwas laufen lassen Command("ping google.com"). Ist dies möglich, um diese Befehle auszugeben, da sie nicht beendet werden, aber ich möchte ihre Protokolle drucken. Bitte vorschlagen.
GrvTyagi
3
@GrvTyagi: Gibt spawnin dieser Antwort ein ChildErgebnis mit Standard-E / A-Streams zurück.
Ry-
Aufbauend auf dieser hervorragenden Antwort fand ich diese Antwort auch hilfreich, um zu verstehen, wie man mit stdin / stdout interagiert.
Michael Noguera
33

Ein sehr klares Beispiel aus den Dokumenten :

use std::process::Command;
let output = Command::new("/bin/cat")
                     .arg("file.txt")
                     .output()
                     .expect("failed to execute process");

println!("status: {}", output.status);
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

assert!(output.status.success());
Karan Ahuja
quelle
8

Es ist tatsächlich möglich! Das entsprechende Modul ist std::run.

let mut options = std::run::ProcessOptions::new();
let process = std::run::Process::new("ls", &[your, arguments], options);

ProcessOptions'Standard-Dateideskriptoren sind standardmäßigNone (Erstellen einer neuen Pipe), sodass Sie process.output()(zum Beispiel) nur zum Lesen aus der Ausgabe verwenden können.

Wenn Sie den Befehl ausführen und alle seine Ausgaben erhalten möchten, nachdem er ausgeführt wurde, gibt es wait_with_outputdafür .

Process::new, seit gestern, gibt übrigens ein Option<Process>statt ein zurück Process.

Ry-
quelle
31
Für alle Suchenden: std :: run wurde entfernt, siehe std::io::processstattdessen (Antwort unten).
jgillich
2
Es ist std::processjetzt ab rustc 1.19.0.
WiSaGaN