Warum Rust die ideale Wahl für CLI-Tools ist?
\n\nHaben 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.
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\nWas brauchen wir?
\n\nZum 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
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\nSchritt 1: Projekt erstellen
\n\nÖffnen Sie das Terminal und geben Sie ein:
\ncargo new log-scanner\ncd log-scanner\n\nCargo 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.
Öffnen Sie Cargo.toml und fügen Sie Abhängigkeiten hinzu, die unseren Code in ein echtes CLI-Tool in Rust verwandeln:
[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
Schritt 2: Argumentstruktur definieren
\n\nDas Coolste an clap sind die derive-Makros. Sie beschreiben einfach die Struktur, und die Magie geschieht von selbst. So sieht das aus:
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\nBeachten 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.
Schritt 3: Suchlogik schreiben
\n\nJetzt 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\nuse 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