CLI-Tools in Rust: Wie Sie Ihr erstes Tool an einem Abend schreiben

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

Warum Rust die ideale Wahl für CLI-Tools ist?

\n\n

Haben Sie sich jemals gefragt, warum alle modernen DevOps-Tools – von bat bis ripgrep und fd – in Rust geschrieben sind? Es geht nicht nur um den Trend. CLI-Tools in Rust sind unglaublich schnell, sicher und, das Beste daran, sie können in eine einzige winzige Binärdatei ohne Abhängigkeiten kompiliert werden. Kein "Haben Sie Java installiert?" oder "Warten Sie, bis Node.js node_modules lädt". Einfach herunterladen – und fertig.

\n\n

In diesem Artikel werden wir ein CLI-Tool in Rust von Grund auf erstellen. Es wird kein abstraktes "Hello, World!" sein, sondern ein echtes nützliches Tool – ein Log-Analyzer, der Fehler sucht, deren Anzahl zählt und die Ergebnisse in einem schönen farbigen Format ausgibt. Und ja, wir schaffen das an einem Abend.

\n\n

Was brauchen wir?

\n\n

Zum Start benötigen wir nur wenig:

\n
    \n
  • Rust (installieren Sie es über rustup, falls noch nicht vorhanden)
  • \n
  • Einen beliebigen Code-Editor (VS Code mit dem rust-analyzer-Plugin ist ideal)
  • \n
  • Ein paar Stunden freie Zeit
  • \n
\n\n

Wenn Sie bereits in Python oder Go programmiert haben, wird Ihnen Rust ungewohnt, aber logisch erscheinen. Die Hauptsache ist, keine Angst vor dem Compiler zu haben. Er ist nicht böse, er ist nur fürsorglich.

\n\n

Schritt 1: Projekt erstellen

\n\n

Öffnen Sie das Terminal und geben Sie ein:

\n
cargo new log-scanner\ncd log-scanner
\n\n

Cargo ist unser Schweizer Taschenmesser. Es hat eine grundlegende Struktur mit Cargo.toml (Abhängigkeitsdatei) und src/main.rs (Einstiegspunkt) erstellt. Sie können bereits cargo run ausführen und "Hello, world!" sehen. Aber wir gehen weiter.

\n\n

Öffnen Sie Cargo.toml und fügen Sie Abhängigkeiten hinzu, die unseren Code in ein echtes CLI-Tool in Rust verwandeln:

\n
[dependencies]\nclap = { version = "4.5", features = ["derive"] }\ncolored = "2.1"\nanyhow = "1.0"
\n\n
    \n
  • clap – Parsing von Befehlszeilenargumenten (unverzichtbar)
  • \n
  • colored – farbige Ausgabe im Terminal
  • \n
  • anyhow – bequeme Fehlerbehandlung
  • \n
\n\n

Schritt 2: Argumentstruktur definieren

\n\n

Das Coolste an clap sind die derive-Makros. Sie beschreiben einfach die Struktur, und die Magie geschieht von selbst. So sieht das aus:

\n\n
use clap::Parser;\n\n#[derive(Parser)]\n#[command(name = "log-scanner")]\n#[command(about = "Scannt Log-Dateien und sucht nach Fehlern")]\nstruct Cli {\n    /// Pfad zur Log-Datei\n    file: String,\n\n    /// Suchbegriff (Standard: "ERROR")\n    #[arg(short, long, default_value = "ERROR")]\n    pattern: String,\n\n    /// Nur die Anzahl der gefundenen Zeilen anzeigen\n    #[arg(short, long)]\n    count: bool,\n}
\n\n

Beachten Sie: Kommentare mit drei Schrägstrichen /// werden automatisch zu Hinweisen in --help. Führen Sie cargo run -- --help aus – und Sie sehen eine sauber generierte Hilfe. Dies ist einer der Gründe, warum die Erstellung von CLI in Rust so angenehm ist: Die Dokumentation schreibt sich von selbst.

\n\n

Schritt 3: Suchlogik schreiben

\n\n

Jetzt kommt der spannendste Teil – das Lesen der Datei und die Suche nach Übereinstimmungen. Rust ist bekannt für seine sichere Datei- und Speicherverarbeitung, aber in der Praxis ist es einfach bequem:

\n\n
use std::fs::File;\nuse std::io::{BufRead, BufReader};\nuse colored::*;\nuse anyhow::Result;\n\nfn scan_log(file_path: &str, pattern: &str, count_only: bool) -> Result<()> {\n    let file = File::open(file_path)?;\n    let reader = BufReader::new(file);\n    let mut total_matches = 0;\n\n    for (line_num, line) in reader.lines().enumerate() {\n        let line = line?;\n        if line.contains(pattern) {\n            total_matches += 1;\n            if !count_only {\n                println!(\n                    "{}:{} {}",\n                    format!("{:>4}", line_num + 1).blue(),\n                    patt                

Blogs

Buchempfehlungen