From fa7fa296db061e45cfdc91c03bdaba72fa43662d Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Thu, 5 Feb 2026 11:39:12 -0500 Subject: [PATCH] Add verbose mode for detailed error messages Added --verbose flag that enables detailed logging: - log_error(): Always shown, critical errors - log_warn(): Shown in verbose mode, potential issues - log_info(): Shown in verbose mode, informational messages Now provides helpful feedback for: - SMART query failures with specific error messages - Missing drive mappings for the current host - Empty bays (no device at configured PCI path) - Ceph command availability and query status - Drive mapping statistics (mapped vs empty) Color-coded output when using --color with --verbose. Fixes: https://code.lotusguild.org/LotusGuild/driveAtlas/issues/14 Co-Authored-By: Claude Opus 4.5 --- driveAtlas.sh | 107 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 11 deletions(-) diff --git a/driveAtlas.sh b/driveAtlas.sh index 50ab63c..a7a7b69 100644 --- a/driveAtlas.sh +++ b/driveAtlas.sh @@ -28,6 +28,7 @@ OPTIONS: -d, --debug Enable debug output (show drive mappings) -s, --skip-smart Skip SMART data collection (faster) -c, --color Enable colored output + --verbose Show detailed error messages and warnings --no-ceph Skip Ceph OSD information --show-pci Show PCI paths in output @@ -35,6 +36,7 @@ EXAMPLES: $(basename "$0") # Normal run with all features $(basename "$0") --skip-smart # Fast run without SMART data $(basename "$0") --color # Run with colored output + $(basename "$0") --verbose # Show all errors and warnings $(basename "$0") --debug # Show mapping debug info ENVIRONMENT VARIABLES: @@ -51,6 +53,7 @@ SKIP_SMART=false SKIP_CEPH=false SHOW_PCI=false USE_COLOR=false +VERBOSE=false while [[ $# -gt 0 ]]; do case "$1" in @@ -82,6 +85,10 @@ while [[ $# -gt 0 ]]; do USE_COLOR=true shift ;; + --verbose) + VERBOSE=true + shift + ;; *) echo "Unknown option: $1" >&2 echo "Use --help for usage information." >&2 @@ -175,6 +182,52 @@ colorize_header() { fi } +#------------------------------------------------------------------------------ +# log_error +# +# Logs an error message to stderr. Always shown regardless of verbose mode. +# Args: $1 - error message +#------------------------------------------------------------------------------ +log_error() { + if [[ "$USE_COLOR" == true ]]; then + echo -e "${COLOR_RED}ERROR:${COLOR_RESET} $1" >&2 + else + echo "ERROR: $1" >&2 + fi +} + +#------------------------------------------------------------------------------ +# log_warn +# +# Logs a warning message to stderr. Only shown in verbose mode. +# Args: $1 - warning message +#------------------------------------------------------------------------------ +log_warn() { + if [[ "$VERBOSE" == true ]]; then + if [[ "$USE_COLOR" == true ]]; then + echo -e "${COLOR_YELLOW}WARN:${COLOR_RESET} $1" >&2 + else + echo "WARN: $1" >&2 + fi + fi +} + +#------------------------------------------------------------------------------ +# log_info +# +# Logs an informational message to stderr. Only shown in verbose mode. +# Args: $1 - info message +#------------------------------------------------------------------------------ +log_info() { + if [[ "$VERBOSE" == true ]]; then + if [[ "$USE_COLOR" == true ]]; then + echo -e "${COLOR_CYAN}INFO:${COLOR_RESET} $1" >&2 + else + echo "INFO: $1" >&2 + fi + fi +} + #------------------------------------------------------------------------------ # Dependency Checks # Verifies required commands are available before running @@ -499,17 +552,28 @@ build_drive_map() { declare -g -A DRIVE_MAP=() declare -g -A BAY_TO_PCI_PATH=() - if [[ -n "$mapping" ]]; then - while read -r path slot; do - [[ -z "$path" || -z "$slot" ]] && continue - - BAY_TO_PCI_PATH[$slot]="$path" - if [[ -L "/dev/disk/by-path/$path" ]]; then - local drive="$(readlink -f "/dev/disk/by-path/$path" | sed 's/.*\///')" - DRIVE_MAP[$slot]="$drive" - fi - done <<< "$mapping" + if [[ -z "$mapping" ]]; then + log_warn "No drive mapping found for host '$host'. Run diagnose-drives.sh to create one." + return fi + + local mapped_count=0 + local empty_count=0 + while read -r path slot; do + [[ -z "$path" || -z "$slot" ]] && continue + + BAY_TO_PCI_PATH[$slot]="$path" + if [[ -L "/dev/disk/by-path/$path" ]]; then + local drive="$(readlink -f "/dev/disk/by-path/$path" | sed 's/.*\///')" + DRIVE_MAP[$slot]="$drive" + ((mapped_count++)) + else + log_info "Bay $slot: No device at PCI path $path" + ((empty_count++)) + fi + done <<< "$mapping" + + log_info "Mapped $mapped_count drives, $empty_count empty bays" } #------------------------------------------------------------------------------ @@ -530,9 +594,12 @@ build_ceph_cache() { # Skip if ceph-volume is not available if ! command -v ceph-volume &>/dev/null; then + log_info "ceph-volume not found, skipping Ceph OSD detection" return fi + log_info "Querying Ceph OSD information..." + # Parse ceph-volume lvm list output # Format: blocks starting with "====== osd.X =======" followed by device info local current_osd="" @@ -549,9 +616,12 @@ build_ceph_cache() { # Skip if ceph command is not available if ! command -v ceph &>/dev/null; then + log_info "ceph CLI not found, skipping OSD status detection" return fi + log_info "Querying Ceph OSD status..." + # Parse ceph osd tree for status # Format: ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT while IFS= read -r line; do @@ -607,7 +677,22 @@ get_drive_smart_info() { local serial="-" local warnings="" - smart_info="$(sudo smartctl -A -i -H "/dev/$device" 2>/dev/null)" + # Capture both stdout and stderr for better error reporting + local smart_stderr + smart_stderr="$(mktemp)" + smart_info="$(sudo smartctl -A -i -H "/dev/$device" 2>"$smart_stderr")" + local smart_exit=$? + + if [[ $smart_exit -ne 0 && -s "$smart_stderr" ]]; then + log_warn "SMART query failed for $device: $(head -1 "$smart_stderr")" + fi + rm -f "$smart_stderr" + + if [[ -z "$smart_info" ]]; then + log_info "No SMART data available for $device" + echo "HDD|-|✗|-|-|" + return + fi # Temperature parsing - handles multiple formats: # - SATA: "194 Temperature_Celsius ... 35" (value at end of line)