2016-01-27 11 views
6

Ich möchte ein externes Programm über std::process::Command::spawn ausführen. Außerdem möchte ich den Grund wissen, warum der Launch des Prozesses fehlgeschlagen ist: liegt es daran, dass der angegebene Programmname nicht existiert/nicht in PATH oder wegen eines anderen Fehlers?Überprüfen, ob ein Befehl in PATH/ausführbar ist als Prozess

Beispiel-Code von dem, was ich erreichen möchte:

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 :("); 
     } 
    }, 
} 

Wenn ich versuche, ein Programm auszuführen, das nicht auf meinem System ist, erhalte ich:

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

Aber ich nicht darauf verlassen wollen. Gibt es eine Möglichkeit festzustellen, ob ein Programm in PATH existiert?

Antwort

6

Sie können e.kind() verwenden, um zu finden, was ErrorKind der Fehler war.

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: ich keine explizite Dokumentation finden war, was Fehlerarten zurückgeführt werden kann, so sah ich den Quellcode auf. Es scheint, dass der Fehler direkt vom Betriebssystem zurückgegeben wird. Der entsprechende Code scheint in src/libstd/sys/[unix/windows/..]/process.rs zu sein. Ein Ausschnitt aus der Unix-Version:

Ein weiterer edit: Auf einem zweiten Gedanken, ich bin nicht sicher, ob die Lizenzen Teile Rust Quellen tatsächlich ermöglicht hier veröffentlichen, so dass Sie es auf github

sehen Was nur Error::from_raw_os_err(...) zurückgibt. Die Windows-Version schien komplizierter, und ich konnte nicht sofort finden, wo es sogar Fehler zurückgibt. So oder so, es scheint, dass Sie in diesem Fall Ihrem Betriebssystem ausgeliefert sind. Zumindest fand ich den folgenden Test in src/libstd/process.rs:

Das gleiche wie oben: github

Das zu garantieren scheint, dass ein ErrorKind::NotFound sollte mindestens zurückgegeben werden, wenn die binären nicht gefunden wird. Es ist sinnvoll anzunehmen, dass das Betriebssystem in anderen Fällen keinen NotFound-Fehler gibt, aber wer weiß. Wenn Sie absolut sicher sein wollen, dass das Programm wirklich nicht gefunden wurde, müssen Sie die Verzeichnisse in $ PATH manuell suchen. Etwas wie:

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

Danke :) Allerdings habe ich ein bisschen mehr eingehende Antwort erwartet. Mit Links zu man-Seiten und/oder anderer Dokumentation. Meine 'if'-Bedingung sollte nur dann ausgewertet werden, wenn das Programm nicht gefunden wurde. Ist das der Fall? Gibt es weitere Informationen darüber, wann welcher Fehler zurückgegeben wird? –

+0

Das PATH-Trennzeichen ist ';' unter Windows! –

+0

@ FrancisGagné und das Verzeichnis Trennzeichen '\'. Mein Beispiel war in der Tat nur Unix. Wahrscheinlich hätte ich das erwähnen sollen. – jkiiski

Verwandte Themen