идея контролировать атрибуты винчестера в автоматическом порядке, при этом не создавая лишней нагрузки на файловую систему, значит: запись только если поменялись критические значения, некритические есть в файле для конкретного винчестера, учитывая что производители могут быть разными как и атрибуты у моделей
помогали несколько движков ИИ, не с первого далеко раза
периоды запуска реализованы через cron
заморачиваться с передачей названия диска в строке не стал
вероятно этот велосипед умрет с этой системой
реализация дополнится отсылкой почты админу
в телеграмме ньюанс насчет перевода на новые строки, меня не раздражает, даже некий юни- шарм
=========== smart_sda.bash
DISK="/dev/sda" NON_CRITICAL_FILE="/opt/smart/smart_non_critical_sda.txt" # Load configuration from external file CONFIG_FILE="/opt/smart/smart_v2.conf" if [ ! -f "$CONFIG_FILE" ]; then echo "Configuration file not found at $CONFIG_FILE. Please create it." >&2 exit 1 fi source "$CONFIG_FILE" # Generate file paths based on disk name DISK_NAME=$(basename "$DISK") # e.g., "sda" from "/dev/sda"
LOG_FILE="/dev/null" # Override log file to /dev/null
STATE_FILE="$BASE_DATA_DIR/smart_state_${DISK_NAME}.txt" DISK_INFO_FILE="$BASE_DATA_DIR/smart_disk_info_${DISK_NAME}.txt" # Ensure base directories exist mkdir -p "$BASE_DATA_DIR" 2>/dev/null # Ensure smartctl is installed if ! command -v "$SMARTCTL" &> /dev/null; then echo "smartctl not found. Please install smartmontools." >> "$LOG_FILE" exit 1 fi # Ensure non-critical attributes file exists if [ ! -f "$NON_CRITICAL_FILE" ]; then echo "Non-critical attributes file not found at $NON_CRITICAL_FILE" >> "$LOG_FILE" exit 1 fi # Read non-critical attributes into an array, extracting only the first field (number) mapfile -t NON_CRITICAL < <(grep -v '^\s*#' "$NON_CRITICAL_FILE" | grep -v '^\s*$' | awk '{print $1}') # Function to check if attribute is non-critical is_non_critical() { local attr_id=$1 for nc in "${NON_CRITICAL[@]}"; do if [ "$nc" == "$attr_id" ]; then return 0 fi done return 1 } # Function to get SMART attributes get_smart_attributes() { local output output=$("$SMARTCTL" -n standby -A "$DISK" 2>&1) if [ $? -ne 0 ]; then echo "Error executing smartctl -A on $DISK: $output" >> "$LOG_FILE" exit 1 fi echo "$output" | awk '/^[ 0-9]/ { print $1, $2, $10 }' } # Function to get disk info (name and serial number) - handles multi-word models get_disk_info() { local output output=$("$SMARTCTL" -i "$DISK" 2>&1) if [ $? -ne 0 ]; then echo "Error executing smartctl -i on $DISK: $output" >> "$LOG_FILE" exit 1 fi echo "$output" | awk ' /Device Model/ { out = "Device Model: "; for (i=3; i<=NF; i++) out = out $i (i<NF ? " " : ""); print out } /Serial Number/ { out = "Serial Number: "; for (i=3; i<=NF; i++) out = out $i (i<NF ? " " : ""); print out } ' } # Save disk info if file doesn't exist if [ ! -f "$DISK_INFO_FILE" ]; then get_disk_info > "$DISK_INFO_FILE" fi # Main logic timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo "[$timestamp] Checking SMART attributes for $DISK" >> "$LOG_FILE" # Get current SMART data current_data=$(get_smart_attributes) if [ -z "$current_data" ]; then echo "[$timestamp] No SMART data retrieved for $DISK." >> "$LOG_FILE" exit 0 fi # Flag to track if changes were found changes_detected=false telegram_message="" # Check if previous data exists if [ -f "$STATE_FILE" ]; then previous_data=$(cat "$STATE_FILE") # Compare with previous data while IFS= read -r prev_line; do prev_id=$(echo "$prev_line" | awk '{print $1}') prev_name=$(echo "$prev_line" | awk '{print $2}') prev_value=$(echo "$prev_line" | awk '{print $3}') # Find matching line in current data current_line=$(echo "$current_data" | grep "^$prev_id ") if [ -n "$current_line" ]; then current_value=$(echo "$current_line" | awk '{print $3}') # Check if value changed and attribute is not non-critical if [ "$prev_value" != "$current_value" ] && ! is_non_critical "$prev_id"; then echo "[$timestamp] Attribute $prev_id ($prev_name) changed: $prev_value -> $current_value" >> "$LOG_FILE" changes_detected=true telegram_message+="$prev_id ($prev_name): $prev_value -> $current_value\n" fi fi done <<< "$previous_data" fi # Save current data as new state only if changes in critical attributes were detected or no previous state exists if [ "$changes_detected" = true ] || [ ! -f "$STATE_FILE" ]; then echo "$current_data" > "$STATE_FILE" fi # Send Telegram notification if changes were detected if [ "$changes_detected" = true ]; then disk_info=$(cat "$DISK_INFO_FILE") full_message="SMART Changes detected on $DISK at $timestamp\n$disk_info\nChanges:\n$telegram_message" curl_response=$(curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \ -d chat_id="$TELEGRAM_CHAT_ID" \ -d text="$full_message" 2>&1) if [ $? -ne 0 ]; then echo "[$timestamp] Error sending Telegram notification for $DISK: $curl_response" >> "$LOG_FILE" else echo "[$timestamp] Telegram notification sent for $DISK" >> "$LOG_FILE" fi fi======== smart_v2.conf ====
Комментариев нет:
Отправить комментарий