Compare commits

..

2 Commits

Author SHA1 Message Date
76f7aaa64c Bump version to 1.2.0 and update changelog
Update version number and document all changes from the
issue fixes including new features, bug fixes, and
performance improvements.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 10:56:29 -05:00
ef004c621e Fix CPU MHz parsing and memory DIMM display issues
- Fix CPU MHz showing multiple lines by using head -1 and proper regex
- Add CPU max MHz display when available
- Fix memory DIMM table not showing data by improving regex patterns
- Fix Type: field matching other fields like "Type Detail:"
- Filter out bonding_masters from network interfaces list
- Add fallback message when DIMM details cannot be parsed

#17

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 10:55:55 -05:00
2 changed files with 90 additions and 64 deletions

View File

@@ -73,6 +73,8 @@ curl -sL "http://10.10.10.63:3000/LotusGuild/proxDoc/raw/branch/main/proxDoc.sh"
- `--vm-list`: Check VM vitals
- `--ct-list`: Check container vitals
- `--backup`: Review backup health
- `--checks=LIST`: Run only specific checks (comma-separated)
- Valid checks: cpu, ram, memory, storage, disk, network, hardware, temps, services, ceph, vms, containers
## Output Information
@@ -101,10 +103,26 @@ The script provides detailed information about:
## Version
Current Version: 1.1.0
Current Version: 1.2.0
### Changelog
#### v1.2.0
- Fixed variable quoting in disk iteration loops (security)
- Added input validation with whitelist of valid options
- Added examples to help documentation
- Added timeout protection to smartctl and ceph commands
- Added `--checks=` option for selective diagnostics
- Extracted magic strings into named constants
- Added validation for potentially empty variables
- Standardized error handling with cleanup trap
- Added optional logging infrastructure (PROXDOC_LOGFILE)
- Cached disk list and unit files to reduce command overhead
- Added efficient process wait utility function
- Fixed CPU MHz parsing showing multiple values
- Fixed memory DIMM table not displaying data
- Fixed bonding_masters showing as network interface
#### v1.1.0
- Added DriveAtlas integration (`--drives`) for physical drive bay mapping
- Added Ceph cluster health monitoring (`--ceph`)

View File

@@ -1,6 +1,6 @@
#!/bin/bash
VERSION="1.1.0"
VERSION="1.2.0"
###################
# Timeout Configuration
@@ -210,15 +210,21 @@ get_disk_health() {
}
get_cpu_info() {
local cpu_info cpu_cores cpu_mhz
local cpu_info cpu_cores cpu_mhz cpu_max_mhz
cpu_info=$(grep -m 1 -w 'model name' /proc/cpuinfo 2>/dev/null | awk -F: '{print $2}' | xargs)
cpu_cores=$(lscpu 2>/dev/null | grep '^CPU(s):' | awk '{print $2}')
cpu_mhz=$(lscpu 2>/dev/null | grep 'MHz' | awk '{print $4}')
cpu_cores=$(lscpu 2>/dev/null | grep -E '^CPU\(s\):' | awk '{print $2}')
# Get current CPU MHz (first match only) - handle both "CPU MHz:" and "CPU(s) MHz:" formats
cpu_mhz=$(lscpu 2>/dev/null | grep -E '^CPU( )?(max )?MHz:' | head -1 | awk -F: '{print $2}' | xargs)
cpu_max_mhz=$(lscpu 2>/dev/null | grep -E '^CPU max MHz:' | awk -F: '{print $2}' | xargs)
echo -e "${GREEN}CPU Model:${NC} ${cpu_info:-Unknown}"
echo -e "${GREEN}CPU Cores:${NC} ${cpu_cores:-Unknown}"
echo -e "${GREEN}CPU MHz:${NC} ${cpu_mhz:-Unknown}"
if [[ -n "$cpu_max_mhz" ]]; then
echo -e "${GREEN}CPU MHz:${NC} ${cpu_mhz:-Unknown} (max: ${cpu_max_mhz})"
else
echo -e "${GREEN}CPU MHz:${NC} ${cpu_mhz:-Unknown}"
fi
}
get_ram_info() {
@@ -293,33 +299,29 @@ get_motherboard_info() {
get_memory_details() {
echo -e "\n${GREEN}=== Memory DIMM Information ===${NC}"
# Use a more robust parsing approach
local locator size type speed manufacturer
local in_device=false
# Print header
printf "%-12s %-12s %-10s %-12s %-20s\n" "Slot" "Size" "Type" "Speed" "Manufacturer"
printf "%-12s %-12s %-10s %-12s %-20s\n" "----" "----" "----" "-----" "------------"
local locator="" size="" type="" speed="" manufacturer=""
local in_device=false
local dimm_count=0
while IFS= read -r line; do
# Detect start of a memory device section
if [[ "$line" =~ ^Memory[[:space:]]Device ]]; then
# If we have data from previous device, print it
if [[ -n "$locator" && -n "$size" && ! "$size" =~ (No|Not|Installed) ]]; then
# Detect start of a memory device section (may have leading whitespace or not)
if [[ "$line" =~ Memory[[:space:]]+Device$ ]] || [[ "$line" == "Memory Device" ]]; then
# Print previous device if it had valid data
if [[ -n "$locator" && -n "$size" && ! "$size" =~ ^(No|Not)[[:space:]] ]]; then
printf "%-12s %-12s %-10s %-12s %-20s\n" \
"${locator:-N/A}" \
"${size:-N/A}" \
"${type:-N/A}" \
"${speed:-N/A}" \
"${manufacturer:-N/A}"
((dimm_count++))
fi
# Reset variables for new device
locator=""
size=""
type=""
speed=""
manufacturer=""
# Reset for new device
locator="" size="" type="" speed="" manufacturer=""
in_device=true
continue
fi
@@ -327,62 +329,65 @@ get_memory_details() {
# Skip if not in a device section
[[ "$in_device" != true ]] && continue
# Parse fields (case-insensitive, flexible whitespace)
if [[ "$line" =~ ^[[:space:]]*Locator:[[:space:]]*(.+)$ ]] && [[ ! "$line" =~ Bank ]]; then
# Parse fields - be very specific to avoid matching wrong lines
# Locator (but not Bank Locator)
if [[ "$line" =~ ^[[:space:]]*Locator:[[:space:]]*(.+)$ ]] && [[ ! "$line" =~ Bank[[:space:]]*Locator ]]; then
locator="${BASH_REMATCH[1]}"
locator="${locator// /_}" # Replace spaces with underscores
locator="${locator// /_}"
# Size
elif [[ "$line" =~ ^[[:space:]]*Size:[[:space:]]*(.+)$ ]]; then
size="${BASH_REMATCH[1]}"
elif [[ "$line" =~ ^[[:space:]]*Type:[[:space:]]*(.+)$ ]]; then
# Type (exact match, not Type Detail or other Type fields)
elif [[ "$line" =~ ^[[:space:]]*Type:[[:space:]]*([A-Za-z0-9]+)$ ]]; then
type="${BASH_REMATCH[1]}"
# Skip if it's an error or unknown type
[[ "$type" =~ (Unknown|Error|Correction) ]] && type=""
# Only clear if it's truly unknown
[[ "$type" == "Unknown" ]] && type=""
# Speed (exact field)
elif [[ "$line" =~ ^[[:space:]]*Speed:[[:space:]]*(.+)$ ]]; then
speed="${BASH_REMATCH[1]}"
[[ "$speed" =~ Unknown ]] && speed=""
[[ "$speed" == "Unknown" ]] && speed=""
# Manufacturer
elif [[ "$line" =~ ^[[:space:]]*Manufacturer:[[:space:]]*(.+)$ ]]; then
manufacturer="${BASH_REMATCH[1]}"
[[ "$manufacturer" =~ (Unknown|NO DIMM) ]] && manufacturer=""
# Clear common placeholder values
[[ "$manufacturer" =~ ^(Unknown|NO[[:space:]]DIMM|Not[[:space:]]Specified)$ ]] && manufacturer=""
fi
# Empty line marks end of device section
if [[ -z "$line" ]]; then
# Empty line or new section marks end
if [[ -z "$line" ]] || [[ "$line" =~ ^Handle ]]; then
in_device=false
fi
done < <(dmidecode -t memory 2>/dev/null)
# Print last device if it has data
if [[ -n "$locator" && -n "$size" && ! "$size" =~ (No|Not|Installed) ]]; then
# Print last device if valid
if [[ -n "$locator" && -n "$size" && ! "$size" =~ ^(No|Not)[[:space:]] ]]; then
printf "%-12s %-12s %-10s %-12s %-20s\n" \
"${locator:-N/A}" \
"${size:-N/A}" \
"${type:-N/A}" \
"${speed:-N/A}" \
"${manufacturer:-N/A}"
((dimm_count++))
fi
# If no DIMMs were printed, show a message
if [[ $dimm_count -eq 0 ]]; then
echo " (Unable to parse DIMM details from dmidecode)"
fi
# Memory summary
echo -e "\n${GREEN}Memory Summary:${NC}"
# Count slots more reliably
local total_slots=0
local populated=0
# Count slots and populated using simpler grep approach
local total_slots populated
total_slots=$(dmidecode -t memory 2>/dev/null | grep -c "^[[:space:]]*Locator:" | head -1)
# Subtract Bank Locator lines
local bank_locators
bank_locators=$(dmidecode -t memory 2>/dev/null | grep -c "Bank Locator:")
total_slots=$((total_slots - bank_locators))
while IFS= read -r line; do
if [[ "$line" =~ ^[[:space:]]*Locator: ]] && [[ ! "$line" =~ Bank ]]; then
((total_slots++))
fi
done < <(dmidecode -t memory 2>/dev/null)
while IFS= read -r line; do
if [[ "$line" =~ ^[[:space:]]*Size:[[:space:]]*(.+)$ ]]; then
local size_val="${BASH_REMATCH[1]}"
if [[ ! "$size_val" =~ (No|Not|Installed) ]]; then
((populated++))
fi
fi
done < <(dmidecode -t memory 2>/dev/null)
populated=$(dmidecode -t memory 2>/dev/null | grep "^[[:space:]]*Size:" | grep -cv "No Module\|Not Installed")
echo -e " Total Slots: $total_slots"
echo -e " Populated: $populated"
@@ -452,6 +457,9 @@ get_physical_interfaces() {
# Skip loopback
[[ "$iface" == "lo" ]] && continue
# Skip bonding_masters (virtual file, not an interface)
[[ "$iface" == "bonding_masters" ]] && continue
# Skip virtual/firewall interfaces
[[ "$iface" =~ $VIRTUAL_IFACE_PATTERN ]] && continue