From 18d84c94f61634df28fbedc3a776b60fa4073ab7 Mon Sep 17 00:00:00 2001 From: DragonSlayer_14 Date: Sun, 20 Sep 2026 19:06:09 +0200 Subject: [PATCH 1/2] =?UTF-8?q?Fix:=20mount/unmount=20melden=20Fehlschl?= =?UTF-8?q?=C3=A4ge=20jetzt=20korrekt,=20Logs=20im=20Journal=20sichtbar=20?= =?UTF-8?q?und=20persistent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'mount --all'/'unmount --all' gaben bisher immer Ok(()) zurück, selbst wenn einzelne Laufwerkspaare nicht (aus)gehängt werden konnten (nur als Text ausgegeben, nie propagiert) - anders als 'watch'. Dadurch zeigte 'systemctl status smart-mount-mount' nie "failed", egal was beim Booten schiefging. run_mount/run_unmount propagieren Fehlschläge jetzt wie 'watch' als Prozess-Fehler. Zusätzlich: logger_ctdra::set_log_dir() zeigt jetzt auf /var/log/smart-mount statt auf einen zufälligen Temp-Ordner, beide systemd-Units haben ein festes SyslogIdentifier=smart-mount mit explizitem StandardOutput/StandardError=journal (journalctl -t smart-mount zeigt damit alles gebündelt), und smart-mount-mount.service bleibt dank RemainAfterExit=yes nach einem erfolgreichen Lauf als "active (exited)" sichtbar statt sofort wieder auf "inactive" zu springen. Co-Authored-By: Claude Sonnet 5 --- README.md | 9 ++++++++ packaging/systemd/smart-mount-mount.service | 11 +++++++++ packaging/systemd/smart-mount-watch.service | 3 +++ src/cli/mount_cmd.rs | 25 ++++++++++++++++++--- src/main.rs | 6 +++++ 5 files changed, 51 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 48304fa..57b91d5 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,15 @@ sudo systemctl edit smart-mount-watch.timer # OnUnitActiveSec=60s ``` +**Logs:** beide Units schreiben mit festem `SyslogIdentifier=smart-mount` ins systemd-Journal - +`journalctl -u smart-mount-mount` / `-u smart-mount-watch` (oder gebündelt `journalctl -t +smart-mount`) zeigt sie an. Zusätzlich schreibt smart-mount dieselben Meldungen dauerhaft nach +`/var/log/smart-mount/log-.log` (siehe `settings.log_level` für die Ausführlichkeit, +Standard `info`) - unabhängig von der Journal-Rotation. `smart-mount-mount.service` bleibt nach +einem erfolgreichen Lauf als "active (exited)" sichtbar (`RemainAfterExit=yes`), und ein +Fehlschlag beim Mounten mindestens eines konfigurierten Laufwerkspaars lässt den Dienst jetzt +auch tatsächlich als "failed" erscheinen, statt es stillschweigend zu ignorieren. + ### Cron-Fallback (Systeme ohne systemd) Ist beim Installieren/Upgraden des Pakets kein `systemctl` gefunden, aber `/etc/cron.d` diff --git a/packaging/systemd/smart-mount-mount.service b/packaging/systemd/smart-mount-mount.service index 9027017..f02f959 100644 --- a/packaging/systemd/smart-mount-mount.service +++ b/packaging/systemd/smart-mount-mount.service @@ -5,7 +5,18 @@ Wants=network-online.target [Service] Type=oneshot +# Bleibt nach einem erfolgreichen Lauf als "active (exited)" sichtbar (statt sofort wieder +# "inactive") - macht in 'systemctl status' auf einen Blick erkennbar, dass der letzte Boot-Lauf +# tatsächlich durchlief, statt nur "inactive" zu zeigen (das genauso gut "nie gelaufen" heißen +# könnte). +RemainAfterExit=yes ExecStart=/usr/bin/smart-mount mount --all +# Explizit (statt sich auf den systemd-Standard zu verlassen): stdout/stderr gehen ins Journal, +# unter einem festen, von der jeweiligen Unit unabhängigen Tag - 'journalctl -t smart-mount' +# zeigt damit die Ausgaben aller smart-mount-Units gebündelt. +StandardOutput=journal +StandardError=journal +SyslogIdentifier=smart-mount [Install] WantedBy=multi-user.target diff --git a/packaging/systemd/smart-mount-watch.service b/packaging/systemd/smart-mount-watch.service index 144b687..252e684 100644 --- a/packaging/systemd/smart-mount-watch.service +++ b/packaging/systemd/smart-mount-watch.service @@ -4,3 +4,6 @@ Description=smart-mount: check reachability and switch local/cloud if needed [Service] Type=oneshot ExecStart=/usr/bin/smart-mount watch +StandardOutput=journal +StandardError=journal +SyslogIdentifier=smart-mount diff --git a/src/cli/mount_cmd.rs b/src/cli/mount_cmd.rs index d1f36ba..61f311d 100644 --- a/src/cli/mount_cmd.rs +++ b/src/cli/mount_cmd.rs @@ -2,7 +2,7 @@ use crate::config::{self, DrivePair}; use crate::db::credentials::CredentialStore; -use crate::reconcile; +use crate::reconcile::{self, Action}; fn select_pairs( cfg: &crate::config::AppConfig, @@ -32,9 +32,21 @@ pub async fn run_mount(name: Option, all: bool) -> anyhow::Result<()> { ); let creds = CredentialStore::open().await?; + let mut had_failure = false; for pair in &pairs { let outcome = reconcile::reconcile_pair(pair, &cfg.settings, &creds).await; print_outcome(&outcome); + if matches!(outcome.action, Action::Failed(_)) { + had_failure = true; + } + } + + // Ohne dies wäre `smart-mount-mount.service` (siehe packaging/systemd/) beim Booten selbst + // dann "erfolgreich" (Exit-Code 0), wenn tatsächlich kein einziges Laufwerkspaar gemountet + // werden konnte - `systemctl status` würde den Fehlschlag also nie sichtbar machen. Analog + // zu `watch::run` unten. + if had_failure { + anyhow::bail!("at least one drive pair could not be mounted"); } Ok(()) } @@ -52,17 +64,24 @@ pub async fn run_unmount(name: Option, all: bool) -> anyhow::Result<()> &format!("unmount: processing {} drive pair(s)", pairs.len()), ); + let mut had_failure = false; for pair in &pairs { match reconcile::unmount_pair(pair, &cfg.settings).await { Ok(_) => println!("{} ({}): unmounted", pair.name, pair.id), - Err(e) => println!("{} ({}): ERROR: {e}", pair.name, pair.id), + Err(e) => { + println!("{} ({}): ERROR: {e}", pair.name, pair.id); + had_failure = true; + } } } + + if had_failure { + anyhow::bail!("at least one drive pair could not be unmounted"); + } Ok(()) } pub(crate) fn print_outcome(outcome: &reconcile::ReconcileOutcome) { - use reconcile::Action; let action_str = match &outcome.action { Action::NoOp => "no change".to_string(), Action::MountedLocal => "mounted local".to_string(), diff --git a/src/main.rs b/src/main.rs index 323f24a..66a830d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,12 @@ use smart_mount::cli; async fn main() -> ExitCode { smart_mount::config::init(); + // Persistentes, gut auffindbares Log-Verzeichnis statt logger-ctdras Standard-Fallback + // (ein Ordner im System-Temp-Verzeichnis, siehe logger-ctdra-Doku) - smart-mount läuft + // ausschließlich als root/System-Dienst (siehe crate::systemd), daher immer derselbe, + // feste Pfad. Muss vor dem ersten Log-Aufruf stehen (siehe logger_ctdra::set_log_dir). + logger_ctdra::set_log_dir("/var/log/smart-mount"); + let log_level = match smart_mount::config::pairs::load() { Ok(cfg) => cfg.settings.log_level, Err(_) => "info".to_string(), From c4a415e3e4a5e36ecb8c3722ffc1921407699ed2 Mon Sep 17 00:00:00 2001 From: Gitea-Bot Date: Sun, 20 Sep 2026 17:17:13 +0000 Subject: [PATCH 2/2] =?UTF-8?q?Chore:=20Erh=C3=B6ht=20Patch-Version=20auf?= =?UTF-8?q?=202.0.3=20f=C3=BCr=20Promotion=20nach=20testing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2beb439..da05f24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2052,7 +2052,7 @@ checksum = "ba467056f1b547ed52077911161fc86985becbc60e8e1857c8a144dab0def891" [[package]] name = "smart-mount" -version = "2.0.2" +version = "2.0.3" dependencies = [ "aes-gcm 0.11.1", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index ba144d5..39b1bc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "smart-mount" -version = "2.0.2" +version = "2.0.3" edition = "2024" authors = ['DragonSlayer_14'] readme = "README.md"