2016-01-27 13 views
6

Voglio eseguire un programma esterno tramite std::process::Command::spawn. Inoltre voglio sapere il motivo per cui spawnare il processo non è riuscito: è perché il nome del programma specificato non esiste/non è in PATH o a causa di un errore diverso?Verificare se un comando è in PATH/eseguibile come processo

codice di esempio di quello che voglio realizzare:

match Command::new("rustc").spawn() { 
    Ok(_) => println!("Was spawned :)"), 
    Err(e) => { 
     if /* ??? */ { 
      println!("`rustc` was not found! Check your PATH!") 
     } else { 
      println!("Some strange error occurred :("); 
     } 
    }, 
} 

Quando si tenta di eseguire un programma che non è sul mio sistema, ottengo:

Error { repr: Os { code: 2, message: "No such file or directory" } } 

ma non lo faccio voglio fare affidamento su questo. C'è un modo per determinare se esiste un programma in PATH?

risposta

6

È possibile utilizzare per individuare l'errore ErrorKind.

match Command::new("rustc").spawn() { 
    Ok(_) => println!("Was spawned :)"), 
    Err(e) => { 
     if let NotFound = e.kind() { 
      println!("`rustc` was not found! Check your PATH!") 
     } else { 
      println!("Some strange error occurred :("); 
     } 
    }, 
} 

Edit: non ho trovato alcuna documentazione esplicito su quali tipi di errore possono essere restituiti, così ho guardato il codice sorgente. Sembra che l'errore sia stato restituito direttamente dal sistema operativo. Il codice pertinente sembra essere in src/libstd/sys/[unix/windows/..]/process.rs. Un frammento della versione Unix:

Un altro edit: Su un secondo pensiero, non sono sicuro se le licenze in realtà permette di inviare parti di fonti Rust qui, in modo da poter vedere su github

Che restituisce appena Error::from_raw_os_err(...). La versione di Windows sembrava più complicata e non sono riuscito a trovare immediatamente da dove vengono restituiti gli errori. Ad ogni modo, sembra che tu sei in balia del tuo sistema operativo in merito. Almeno ho trovato il seguente test in src/libstd/process.rs:

Idem come sopra: github

che sembra garantire che un ErrorKind::NotFound dovrebbe essere restituito almeno quando il binario non viene trovato. Ha senso presumere che il sistema operativo non darebbe un errore NotFound in altri casi, ma chissà. Se vuoi essere assolutamente sicuro che il programma non sia stato trovato, dovrai cercare manualmente le directory in $ PATH. Qualcosa di simile:

use std::env; 
use std::fs; 

fn is_program_in_path(program: &str) -> bool { 
    if let Ok(path) = env::var("PATH") { 
     for p in path.split(":") { 
      let p_str = format!("{}/{}", p, program); 
      if fs::metadata(p_str).is_ok() { 
       return true; 
      } 
     } 
    } 
    false 
} 

fn main() { 
    let program = "rustca"; // shouldn't be found 
    if is_program_in_path(program) { 
     println!("Yes."); 
    } else { 
     println!("No."); 
    } 
} 
+0

Grazie :) Tuttavia, mi aspettavo una risposta un po 'più approfondita. Con collegamenti a pagine man e/o altra documentazione. La mia condizione 'if' dovrebbe valutare se e solo se il programma non è stato trovato. È questo il caso? C'è più informazioni su quando viene restituito l'errore? –

+0

Il separatore PATH è ';' su Windows! –

+0

@ FrancisGagné e il separatore di directory '\'. Il mio esempio era in effetti solo per Unix. Probabilmente avrebbe dovuto dirlo. – jkiiski

Problemi correlati