diff --git a/driveAtlas.sh b/driveAtlas.sh index 41a378d..c5a0873 100644 --- a/driveAtlas.sh +++ b/driveAtlas.sh @@ -11,8 +11,25 @@ # Note: Not using -u (nounset) as script uses ${var:-default} patterns set -o pipefail +# Require bash 4.2+ for declare -g -A (global associative arrays) +if ((BASH_VERSINFO[0] < 4 || (BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] < 2))); then + echo "ERROR: This script requires Bash 4.2 or higher (current: $BASH_VERSION)" >&2 + exit 1 +fi + VERSION="1.1.0" +#------------------------------------------------------------------------------ +# Cleanup Trap +# Ensures temporary directories are removed on exit or interruption +#------------------------------------------------------------------------------ +cleanup() { + if [[ -n "${SMART_CACHE_DIR:-}" && -d "$SMART_CACHE_DIR" ]]; then + rm -rf "$SMART_CACHE_DIR" + fi +} +trap cleanup EXIT INT TERM + #------------------------------------------------------------------------------ # Path Constants # Centralized path definitions to avoid hardcoding throughout the script @@ -607,7 +624,7 @@ get_storage_controllers() { # Values: PCI path strings (for --show-pci option) #------------------------------------------------------------------------------ build_drive_map() { - local host="$(hostname)" + local host="$(hostname | tr -cd '[:alnum:]-_.')" local mapping="${SERVER_MAPPINGS[$host]}" # Declare global arrays directly @@ -886,7 +903,7 @@ get_drive_smart_info() { # Main Display Logic #------------------------------------------------------------------------------ -HOSTNAME=$(hostname) +HOSTNAME=$(hostname | tr -cd '[:alnum:]-_.') CHASSIS_TYPE=${CHASSIS_TYPES[$HOSTNAME]:-"unknown"} # Display chassis layout @@ -977,15 +994,22 @@ if [[ "$SKIP_SMART" != true ]]; then SMART_CACHE_DIR="$(mktemp -d)" log_info "Collecting SMART data in parallel..." + local max_parallel_jobs=10 + local job_count=0 for bay in $all_bays; do device="${DRIVE_MAP[$bay]}" if [[ -n "$device" && "$device" != "EMPTY" && -b "/dev/$device" ]]; then # Launch background job to collect raw smartctl data (sudo smartctl -A -i -H "/dev/$device" > "$SMART_CACHE_DIR/${device}.raw" 2>/dev/null) & + ((job_count++)) + if ((job_count >= max_parallel_jobs)); then + wait -n 2>/dev/null || wait # wait -n requires bash 4.3+, fall back to wait + ((job_count--)) + fi fi done - # Wait for all background SMART queries to complete + # Wait for all remaining background SMART queries to complete wait log_info "SMART data collection complete" fi @@ -1078,11 +1102,6 @@ for bay in $all_bays; do fi done -# Clean up SMART cache directory -if [[ -n "${SMART_CACHE_DIR:-}" && -d "$SMART_CACHE_DIR" ]]; then - rm -rf "$SMART_CACHE_DIR" -fi - # NVMe drives (only show unmapped ones - mapped NVMe drives appear in main table) nvme_devices=$(lsblk -d -n -o NAME,SIZE | grep "^nvme" 2>/dev/null) if [[ -n "$nvme_devices" ]]; then