Befehle in Rust ausführen: Wie man die Ausgabe im Jahr 2025 erfasst

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Von Python zu Rust: Die Evolution der Befehlsausführung

\n\n

Wenn Sie sich jemals auf Stack Overflow die Frage gestellt haben „How do I invoke a system command and capture its output?“, dann wissen Sie: Dies ist eine der beliebtesten und lebenswichtigsten Fragen für jeden Entwickler. In der Welt von Python ist die Antwort einfach — subprocess.check_output(). Aber was tun, wenn Sie zu Rust gewechselt sind und einen Befehl nicht nur ausführen, sondern dies elegant, sicher und mit maximaler Leistung tun möchten?

\n\n

Rust ist nicht nur „eine weitere Sprache“. Es ist ein System, bei dem jedes Byte unter Kontrolle ist und Ausführungsfehler von Befehlen nicht zum Absturz der gesamten Anwendung führen. Im Jahr 2025, wenn Sicherheit und Geschwindigkeit zum De-facto-Standard geworden sind, ist die Fähigkeit, richtig mit Unterprozessen in Rust zu arbeiten, eine Must-have-Fähigkeit. Lassen Sie uns die Best Practices durchgehen, die die Ausführung von Systembefehlen von einer Routine zur Kunst machen.

\n\n

std::process::Command: Ihr Schweizer Taschenmesser

\n\n

Das Herz der Befehlsausführung in Rust ist das Modul std::process::Command. Es bietet alles Notwendige zum Starten externer Programme, Erfassen ihrer Ausgabe und Behandeln von Fehlern. Im Gegensatz zu Python, wo subprocess viele Details verbirgt, gibt Ihnen Rust die volle Kontrolle.

\n\n

Basisbeispiel: stdout erfassen

\n\n

Beginnen wir mit dem Klassiker — führen wir den Befehl echo "Hello, Rust!" aus und erfassen seine Ausgabe:

\n\n
use std::process::Command;\n\nfn main() -> Result<(), Box<dyn std::error::Error>> {\n    let output = Command::new("echo")\n        .arg("Hello, Rust!")\n        .output()?;\n\n    let stdout = String::from_utf8(output.stdout)?;\n    println!("Ausgabe des Befehls: {}", stdout);\n\n    Ok(())\n}\n
\n\n

Was ist hier wichtig? Wir verwenden .output(), das eine Struktur Output zurückgibt. Sie enthält drei Felder: stdout, stderr und status. Beachten Sie das ? — dies ist der Fehlerweitergabeoperator, der uns vor umständlichen match-Blöcken bewahrt. Rust zwingt uns, mögliche Fehler explizit zu behandeln: Der Befehl könnte nicht existieren, keine Zugriffsrechte haben oder einfach mit einem Fehler beendet werden.

\n\n

Behandlung von stderr und Rückgabecode

\n\n

In realen Szenarien benötigen Sie nicht nur stdout, sondern auch stderr. Stellen Sie sich vor, Sie führen ls /nonexistent aus — ein Befehl, der garantiert einen Fehler ausgibt:

\n\n
use std::process::Command;\n\nfn main() {\n    let output = Command::new("ls")\n        .arg("/nonexistent")\n        .output()\n        .expect("Befehl konnte nicht ausgeführt werden");\n\n    if output.status.success() {\n        let stdout = String::from_utf8_lossy(&output.stdout);\n        println!("Erfolg: {}", stdout);\n    } else {\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        eprintln!("Fehler (Code {}): {}", output.status.code().unwrap_or(-1), stderr);\n    }\n}\n
\n\n

Hier verwenden wir String::from_utf8_lossy() — eine sichere Methode zur Umwandlung von Bytes in einen String, die ungültige UTF-8-Zeichen durch � ersetzt. Dies ist kritisch, wenn die Ausgabe des Befehls Binärdaten enthält oder eine unvorhersehbare Kodierung verwendet.

\n\n

Fortgeschrittene Techniken: Asynchronität und Pipes

\n\n

Im Jahr 2025 ist die synchrone Ausführung von Befehlen veraltet. Moderne Anwendungen erfordern Asynchronität, insbesondere wenn Sie mit Webservern arbeiten oder viele Befehle gleichzeitig verarbeiten. Rust mit seinem Tokio-Ökosystem bietet eine elegante Lösung.

\n\n

Asynchrone Erfassung der Ausgabe mit Tokio

\n\n

Fügen wir die Abhängigkeit in Cargo.toml hinzu:

\n\n
[dependencies]\ntokio = { version = "1", features = ["full"] }\n
\n\n

Jetzt führen wir den Befehl asynchron aus:

\n\n
use tokio::process::Command;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let output = Command::new("sleep")\n        .arg("2")\n        .output()\n                

Blogs

Buchempfehlungen