Jak wywołać polecenie systemowe w Rust i przechwycić jego dane wyjściowe?

87

Czy istnieje sposób wywołania polecenia systemowego, takiego jak lslub fuserw Rust? Co powiesz na uchwycenie jego wyników?

quux00
źródło

Odpowiedzi:

115

std::process::Command na to pozwala.

Istnieje wiele sposobów tworzenia procesu potomnego i wykonania dowolnego polecenia na komputerze:

  • spawn - uruchamia program i zwraca wartość ze szczegółami
  • output - uruchamia program i zwraca wynik
  • status - uruchamia program i zwraca kod zakończenia

Jeden prosty przykład z dokumentacji:

use std::process::Command;

Command::new("ls")
        .arg("-l")
        .arg("-a")
        .spawn()
        .expect("ls command failed to start");
tales
źródło
2
A jeśli potrzebuję uzyskać dane wyjściowe w czasie rzeczywistym. Myślę, że outputfunkcja zwraca Vec po zakończeniu procesu. A więc na wypadek gdybyśmy uruchomili coś takiego Command("ping google.com"). Czy jest to możliwe, aby uzyskać wyjście tego polecenia, ponieważ nie zakończy się, ale chcę wydrukować jego dzienniki. Proszę zasugeruj.
GrvTyagi
3
@GrvTyagi:, spawnwspomniany w tej odpowiedzi, zwraca Childwynik ze standardowymi strumieniami I / O.
Ry-
Opierając się na tej doskonałej odpowiedzi, uznałem również, że ta odpowiedź jest pomocna w zrozumieniu interakcji ze stdin / stdout.
Michael Noguera
33

bardzo jasny przykład z dokumentacji :

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
źródło
8

To rzeczywiście możliwe! Odpowiednim modułem jest std::run.

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

ProcessOptions'standardowe deskryptory plików domyślnieNone (utwórz nowy potok), więc możesz po prostu użyć process.output()(na przykład) do odczytu z jego wyjścia.

Jeśli chcesz uruchomić polecenie i uzyskać wszystkie jego dane wyjściowe po jego zakończeniu, jest wait_with_outputna to .

Process::newnawiasem mówiąc , od wczoraj zwraca an Option<Process>zamiast a Process.

Ry-
źródło
31
Dla wszystkich wyszukiwarek: std :: run został usunięty, zobacz std::io::processzamiast tego (odpowiedź poniżej).
jgillich
2
Jest std::processteraz od rustc 1.19.0.
WiSaGaN