commit ab304eb9cb6af87547b876797e090cc4a6ce2e52 Author: kqjy Date: Wed Nov 19 03:28:11 2025 +0000 Add chkdsk.sh diff --git a/chkdsk.sh b/chkdsk.sh new file mode 100644 index 0000000..ccda9c8 --- /dev/null +++ b/chkdsk.sh @@ -0,0 +1,355 @@ +#!/bin/bash + +####################################### +# SMART Disk Health Monitor +# Usage: ./script.sh [-a|-s|-h] [--auto-install] +####################################### + +# Color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Flags +AUTO_INSTALL=false + +# Function to print colored output +print_color() { + local color=$1 + shift + echo -e "${color}$@${NC}" +} + +# Function to check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Function to detect package manager +detect_package_manager() { + if command_exists apt-get; then + echo "apt" + elif command_exists yum; then + echo "yum" + elif command_exists dnf; then + echo "dnf" + elif command_exists zypper; then + echo "zypper" + elif command_exists pacman; then + echo "pacman" + elif command_exists apk; then + echo "apk" + else + echo "unknown" + fi +} + +# Function to install smartmontools +install_smartmontools() { + local pkg_mgr=$(detect_package_manager) + + print_color "$YELLOW" "Attempting to install smartmontools..." + + case $pkg_mgr in + apt) + if [ "$EUID" -eq 0 ]; then + apt-get update -qq && apt-get install -y smartmontools + else + sudo apt-get update -qq && sudo apt-get install -y smartmontools + fi + ;; + yum) + if [ "$EUID" -eq 0 ]; then + yum install -y smartmontools + else + sudo yum install -y smartmontools + fi + ;; + dnf) + if [ "$EUID" -eq 0 ]; then + dnf install -y smartmontools + else + sudo dnf install -y smartmontools + fi + ;; + zypper) + if [ "$EUID" -eq 0 ]; then + zypper install -y smartmontools + else + sudo zypper install -y smartmontools + fi + ;; + pacman) + if [ "$EUID" -eq 0 ]; then + pacman -Sy --noconfirm smartmontools + else + sudo pacman -Sy --noconfirm smartmontools + fi + ;; + apk) + if [ "$EUID" -eq 0 ]; then + apk add --no-cache smartmontools + else + sudo apk add --no-cache smartmontools + fi + ;; + *) + print_color "$RED" "Unknown package manager. Cannot auto-install." + return 1 + ;; + esac + + return $? +} + +# Function to prompt for installation +prompt_install() { + local pkg_mgr=$(detect_package_manager) + + if [ "$pkg_mgr" == "unknown" ]; then + print_color "$RED" "ERROR: Unable to detect package manager" + print_color "$YELLOW" "Please install smartmontools manually:" + echo " Debian/Ubuntu: apt-get install smartmontools" + echo " RHEL/CentOS: yum install smartmontools" + echo " Fedora: dnf install smartmontools" + echo " Arch: pacman -S smartmontools" + echo " Alpine: apk add smartmontools" + exit 1 + fi + + print_color "$YELLOW" "smartmontools is not installed." + + if [ "$AUTO_INSTALL" = true ]; then + print_color "$BLUE" "Auto-install enabled. Installing smartmontools..." + if install_smartmontools; then + print_color "$GREEN" "✓ Successfully installed smartmontools" + return 0 + else + print_color "$RED" "✗ Failed to install smartmontools" + exit 1 + fi + else + print_color "$BLUE" "Detected package manager: $pkg_mgr" + echo "" + read -p "Install smartmontools now? [y/N]: " -n 1 -r + echo "" + + if [[ $REPLY =~ ^[Yy]$ ]]; then + if install_smartmontools; then + print_color "$GREEN" "✓ Successfully installed smartmontools" + return 0 + else + print_color "$RED" "✗ Failed to install smartmontools" + exit 1 + fi + else + print_color "$YELLOW" "Installation cancelled. Exiting." + exit 1 + fi + fi +} + +# Function to check required dependencies +check_dependencies() { + local missing_deps=() + local core_missing=() + + # Check core utilities (should be present on all systems) + for cmd in lsblk awk grep; do + if ! command_exists "$cmd"; then + core_missing+=("$cmd") + fi + done + + # If core utilities are missing, fail immediately + if [ ${#core_missing[@]} -ne 0 ]; then + print_color "$RED" "ERROR: Missing core system utilities: ${core_missing[*]}" + print_color "$YELLOW" "Install with your package manager:" + echo " util-linux (for lsblk)" + echo " gawk or mawk (for awk)" + echo " grep (usually pre-installed)" + exit 1 + fi + + # Check if smartctl is available + if ! command_exists smartctl; then + prompt_install + fi +} + +# Function to check root privileges +check_privileges() { + if [ "$EUID" -ne 0 ] && ! sudo -n true 2>/dev/null; then + print_color "$RED" "ERROR: This script requires root privileges" + print_color "$YELLOW" "Run with: sudo $0 $*" + exit 1 + fi +} + +# Function to safely get smartctl data +get_smart_data() { + local drive=$1 + local flags=$2 + local output + + output=$(smartctl $flags "/dev/$drive" 2>/dev/null) + local exit_code=$? + + # Exit codes: Bit 1 (2): Device open failed or doesn't support SMART + if [ $exit_code -eq 2 ] || [ $exit_code -eq 1 ]; then + return 1 + fi + + echo "$output" + return 0 +} + +# Function to display usage +show_usage() { + cat << EOF +Usage: $(basename "$0") [OPTIONS] + +Monitor disk health using SMART data. + +OPTIONS: + -a Full SMART output for all drives + -s Short health summary for all drives + -h Display this help message + --auto-install Auto-install smartmontools without prompting + (default) Table summary of all drives + +EXAMPLES: + $(basename "$0") # Table view (default) + $(basename "$0") -a # Full SMART data + $(basename "$0") -s # Quick health check + $(basename "$0") --auto-install # Install dependencies automatically + +REQUIREMENTS: + - Root/sudo privileges + - smartmontools package (will offer to install if missing) + - util-linux package + +SECURITY NOTE: + Use --auto-install only on trusted systems. Interactive install + is recommended for production environments. + +EOF + exit 0 +} + +# Parse options +mode="table" +for arg in "$@"; do + case $arg in + -a) mode="full" ;; + -s) mode="short" ;; + -h) show_usage ;; + --auto-install) AUTO_INSTALL=true ;; + -*) + print_color "$RED" "Invalid option: $arg" + show_usage + ;; + esac +done + +# Run dependency and privilege checks +check_dependencies +check_privileges + +# Auto-detect all disk devices +mapfile -t drives < <(lsblk -dn -o NAME,TYPE 2>/dev/null | awk '$2=="disk"{print $1}') + +if [ ${#drives[@]} -eq 0 ]; then + print_color "$RED" "ERROR: No disk drives detected" + exit 1 +fi + +# Full mode +if [[ "$mode" == "full" ]]; then + for drive in "${drives[@]}"; do + echo "" + print_color "$BLUE" "=== /dev/$drive ===" + smart_data=$(get_smart_data "$drive" "-a") + if [ $? -eq 0 ]; then + echo "$smart_data" + else + print_color "$RED" " SMART not supported or device unavailable" + fi + echo "" + done + +# Short mode +elif [[ "$mode" == "short" ]]; then + for drive in "${drives[@]}"; do + print_color "$BLUE" "Drive: /dev/$drive" + smart_data=$(get_smart_data "$drive" "-H") + if [ $? -eq 0 ]; then + health=$(echo "$smart_data" | grep -i "SMART overall-health" | awk -F: '{print $2}' | xargs) + if [[ "$health" == "PASSED" ]]; then + print_color "$GREEN" " Health: $health" + else + print_color "$RED" " Health: ${health:-UNKNOWN}" + fi + else + print_color "$RED" " SMART not supported or device unavailable" + fi + echo "" + done + +# Table mode +else + printf "| %-12s | %-22s | %-13s | %-9s | %-18s | %-15s |\n" "Drive" "Model" "Power-On Hrs" "Temp (°C)" "Realloc/MediaErr" "Health" + echo "|--------------|------------------------|---------------|-----------|--------------------|--------------------|" + + for drive in "${drives[@]}"; do + model="N/A" + power="N/A" + temp="N/A" + errors="N/A" + health="UNKNOWN" + + info=$(get_smart_data "$drive" "-i") + if [ $? -ne 0 ]; then + printf "| %-12s | %-22s | %-13s | %-9s | %-18s | %-15s |\n" "/dev/$drive" "SMART N/A" "-" "-" "-" "N/A" + continue + fi + + healthinfo=$(get_smart_data "$drive" "-A -H") + + if [[ "$drive" == nvme* ]]; then + model=$(echo "$info" | awk -F': ' '/Model Number/{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}') + power=$(echo "$healthinfo" | awk -F': ' '/Power On Hours/{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}') + temp=$(echo "$healthinfo" | awk -F': ' '/^Temperature:/{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}' | awk '{print $1}') + media_err=$(echo "$healthinfo" | awk -F': ' '/Media and Data Integrity Errors/{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}') + health=$(echo "$healthinfo" | grep -i "SMART overall-health self-assessment test result" | awk -F': ' '{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}') + errors="${media_err:-0}" + else + model=$(echo "$info" | awk -F': ' '/Device Model:|Product:/{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}' | head -n1) + power=$(echo "$healthinfo" | awk '/Power_On_Hours/{print $10}' | head -n1) + temp=$(echo "$healthinfo" | awk '/Temperature_Celsius|Airflow_Temperature_Cel/{print $10}' | head -n1) + realloc=$(echo "$healthinfo" | awk '/Reallocated_Sector_Ct/{print $10}' | head -n1) + health=$(echo "$healthinfo" | grep -i "SMART overall-health self-assessment test result" | awk -F': ' '{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}') + errors="${realloc:-0}" + fi + + if [ ${#model} -gt 22 ]; then + model="${model:0:19}..." + fi + + model="${model:-N/A}" + power="${power:-N/A}" + temp="${temp:-N/A}" + errors="${errors:-N/A}" + health="${health:-UNKNOWN}" + + printf "| %-12s | %-22s | %-13s | %-9s | %-18s | %-15s |\n" \ + "/dev/$drive" "$model" "$power" "$temp" "$errors" "$health" + done + + echo "" + print_color "$YELLOW" "Note: PASSED = Healthy, FAILED = Replace immediately, N/A = SMART unavailable" +fi + +exit 0