Command::spawn în Rust

Pornește programul și returnează imediat un Child, fără să aștepte; poți comunica cu el și îl aștepți mai târziu.

Sintaxă
fn spawn(&mut self) -> io::Result<Child>

child.wait() -> io::Result<ExitStatus>
child.wait_with_output() -> io::Result<Output>

Ce face Command::spawn

spawn() pornește procesul și îți dă un Child imediat, în timp ce copilul rulează în paralel. Cu child.wait() aștepți să se termine, cu child.wait_with_output() aștepți și strângi ieșirea, cu child.kill() îl oprești.

Împreună cu .stdin(Stdio::piped()) și .stdout(Stdio::piped()), poți trimite date copilului și citi ce răspunde: child.stdin și child.stdout devin Some(...). Închide stdin (cu take() și drop) când ai terminat de scris, altfel copilul așteaptă la nesfârșit.

Ce returnează

io::Result<Child>.

Exemple

Exemplul 1: Trimite date lui sort și citește rezultatul

LC_ALL=C face ca sort să ordoneze la fel pe orice sistem. După scriere, stdin este închis la sfârșitul blocului.

use std::io::Write;
use std::process::{Command, Stdio};

fn main() -> std::io::Result<()> {
    let mut copil = Command::new("sort")
        .env("LC_ALL", "C")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()?;

    {
        let mut intrare = copil.stdin.take().expect("stdin a fost cerut cu piped()");
        intrare.write_all(b"Mihai\nAna\nRadu\nIoana\n")?;
    }

    let iesire = copil.wait_with_output()?;
    print!("{}", String::from_utf8_lossy(&iesire.stdout));
    println!("sort s-a terminat cu: {}", iesire.status);
    Ok(())
}

Rezultat

Ana
Ioana
Mihai
Radu
sort s-a terminat cu: exit status: 0

Exemplul 2: Trei procese în paralel

Toate trei pornesc imediat și lucrează în același timp. Le așteptăm în ordinea pornirii, deci rezultatul are mereu aceeași ordine.

use std::process::{Command, Stdio};

fn main() -> std::io::Result<()> {
    let mut copii = Vec::new();
    for oras in ["Iași", "Cluj", "Sibiu"] {
        let copil = Command::new("sh")
            .args(["-c", "sleep 0.1; echo \"raport gata pentru $0\"", oras])
            .stdout(Stdio::piped())
            .spawn()?;
        copii.push(copil);
    }
    println!("am pornit {} procese", copii.len());

    for copil in copii {
        let o = copil.wait_with_output()?;
        print!("{}", String::from_utf8_lossy(&o.stdout));
    }
    Ok(())
}

Rezultat

am pornit 3 procese
raport gata pentru Iași
raport gata pentru Cluj
raport gata pentru Sibiu

Greșeli frecvente

  • Nu apelezi niciodată wait(): pe Linux și macOS procesul terminat rămâne „zombi” până când părintele îl așteaptă.
  • Uiți să închizi stdin-ul copilului: programe ca sort așteaptă sfârșitul intrării și nu termină niciodată.

Comenzi înrudite

  • Command: Pornește alt program (proces copil): new() alege programul, arg() și args() adaugă argumente.
  • Command::output: Rulează programul, așteaptă să termine și returnează codul de ieșire și tot ce a scris pe stdout și stderr.
  • Command::status: Rulează programul, îl lasă să scrie direct în terminal și returnează doar felul în care s-a terminat.
  • thread::spawn: Pornește un fir de execuție nou care rulează funcția dată; join() așteaptă terminarea lui și îi dă rezultatul.