#!/usr/bin/env bash # Fenris — interactive menu for the NVMe wear monitor & dashboard. # Created by Bongbetic. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PY="$SCRIPT_DIR/fenris.py" PORT_DEFAULT=8420 INTERVAL_DEFAULT=300 banner() { cat <<'EOF' _____ _ | __|___ ___ _| |___ | __| -_| | . | _| |__| |___|_|_|_|___|_| NVMe wear monitor & live dashboard Created by Bongbetic EOF } pause() { read -rp "Press Enter to continue..." _; } detect_device() { # Query Python's auto-detect for the default device. python3 -c "import sys; sys.path.insert(0,'$SCRIPT_DIR'); from fenris import detect_device; print(detect_device())" 2>/dev/null || echo /dev/nvme0 } menu() { clear banner echo echo " 1) Start monitoring (background daemon + dashboard)" echo " 2) Stop monitoring" echo " 3) Status / current wear stats" echo " 4) Take one sample right now" echo " 5) Open dashboard URL" echo " ---" echo " h) Help / how this works" echo " q) Exit" echo read -rp "Choose an option: " choice echo case "$choice" in 1) start_flow ;; 2) python3 "$PY" stop; pause ;; 3) python3 "$PY" status; pause ;; 4) read -rp "Device [default: auto-detect]: " dev if [ -z "$dev" ]; then python3 "$PY" sample; else python3 "$PY" sample --device "$dev"; fi pause ;; 5) show_url; pause ;; h|H) help_text; pause ;; q|Q) echo "Bye. — Fenris, by Bongbetic"; exit 0 ;; *) echo "Invalid choice."; pause ;; esac } start_flow() { read -rp "NVMe device [Enter = auto-detect]: " dev read -rp "Sample interval in seconds [Enter = ${INTERVAL_DEFAULT}]: " interval read -rp "Dashboard port [Enter = ${PORT_DEFAULT}]: " port interval="${interval:-$INTERVAL_DEFAULT}" port="${port:-$PORT_DEFAULT}" args=(start --interval "$interval" --port "$port") if [ -n "${dev:-}" ]; then args+=(--device "$dev"); fi echo echo "Note: reading NVMe SMART data needs root." echo "Fenris runs 'sudo -n smartctl ...' (no-prompt sudo). If this fails," echo "either run this menu with sudo, or allow passwordless smartctl via:" echo " sudo visudo -> youruser ALL=(root) NOPASSWD: /usr/sbin/smartctl" echo python3 "$PY" "${args[@]}" pause } show_url() { if [ -f "$SCRIPT_DIR/data/fenris.pid" ]; then # Try to read actual port from running process cmdline, else guess default. local pid port pid=$(<"$SCRIPT_DIR/data/fenris.pid") port=$(tr '\0' '\n' < /proc/"$pid"/cmdline 2>/dev/null | grep -A1 -- '--port' | tail -1 || true) port="${port:-$PORT_DEFAULT}" echo "Dashboard: http://localhost:${port}" else echo "Fenris is not currently running. Start it first (option 1)." fi } help_text() { cat <