0Pricing
Linux Command Line & Bash Scripting Mastery · Lezione

Creare script per controlli e avvisi sullo stato del sistema

Raccolga metriche su carico, memoria e disco e attivi avvisi basati su soglie da script pianificati.

Creare script per controlli e avvisi sullo stato del sistema è una lezione Linux Command Line & Bash Scripting Mastery gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Linux Command Line & Bash Scripting Mastery, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Linux Command Line & Bash Scripting Mastery include 4 lezioni in totale.

Perché i controlli dello stato del sistema sono importanti

I server di produzione possono degradarsi senza segnali evidenti. Picchi della CPU, perdite di memoria e dischi pieni causano interruzioni, ma solo se nessuno se ne accorge in tempo. Gli script di controllo dello stato del sistema automatizzano il ciclo di monitoraggio: raccolgono le metriche, le confrontano con le soglie e inviano avvisi prima che gli utenti riscontrino problemi.

  • Programmati tramite cron, vengono eseguiti ogni pochi minuti senza intervento umano
  • Producono un output coerente con marca temporale, adatto all'aggregazione dei log
  • La logica basata su soglie mantiene significativi gli avvisi: non ogni breve anomalia attiva una chiamata al team reperibile

In questa lezione costruirà da zero uno script di controllo dello stato adatto alla produzione, aggiungendo un livello alla volta i controlli sul load average, sulla pressione della memoria e sull'utilizzo del disco.

Acquisizione del load average

Linux espone i load average di 1, 5 e 15 minuti tramite /proc/loadavg e il comando uptime. Per gli script, /proc/loadavg è la fonte più pulita: non presenta problemi di localizzazione né variazioni nell'analisi tra le diverse distribuzioni.

Il frammento seguente legge il load average di 1 minuto e lo memorizza in una variabile per il confronto con la soglia. cut estrae il primo campo; awk rimuove la parte decimale per il confronto tra interi usando bc per i calcoli in virgola mobile.

#!/usr/bin/env bash
# Read 1-minute load average from /proc/loadavg
LOAD_RAW=$(cut -d' ' -f1 /proc/loadavg)
echo "Raw load average: $LOAD_RAW"

# Number of CPU cores — used to normalise load
CPU_CORES=$(nproc)
echo "CPU cores: $CPU_CORES"

# Compute load percentage (load / cores * 100) using bc
LOAD_PCT=$(echo "scale=2; $LOAD_RAW / $CPU_CORES * 100" | bc)
echo "Load %: $LOAD_PCT"

Confronto con soglie in virgola mobile

Bash non è in grado di confrontare nativamente numeri in virgola mobile: [ 1.5 -gt 1.2 ] genera un errore. Le due soluzioni idiomatiche sono:

  • bc — restituisce 1 (vero) o 0 (falso) a partire da un'espressione di confronto
  • awk — può valutare condizioni in virgola mobile all'interno di una pipeline

L'uso di bc mantiene la logica leggibile e facile da testare. Lo schema $(echo "$A > $B" | bc) restituisce 1 quando la condizione è verificata; può testarlo con [ ... -eq 1 ].

#!/usr/bin/env bash
LOAD_RAW=$(cut -d' ' -f1 /proc/loadavg)
CPU_CORES=$(nproc)
THRESHOLD=80  # alert when load % exceeds 80%

LOAD_PCT=$(echo "scale=2; $LOAD_RAW / $CPU_CORES * 100" | bc)

# bc returns 1 if the expression is true
if [ "$(echo "$LOAD_PCT > $THRESHOLD" | bc)" -eq 1 ]; then
    echo "ALERT: Load is ${LOAD_PCT}% (threshold ${THRESHOLD}%)"
else
    echo "OK: Load is ${LOAD_PCT}%"
fi

Raccolta delle metriche della memoria

/proc/meminfo è la fonte autorevole per le statistiche della memoria in Linux. Campi principali:

  • MemTotal — RAM fisica totale in kB
  • MemAvailable — quantità stimata in kB disponibile per nuove allocazioni senza ricorrere allo swap (più indicativa di MemFree)

Usare awk con una ricerca per modello è il modo più pulito per estrarre questi valori. Dividendo MemAvailable per MemTotal e sottraendo il risultato da 100 si ottiene la percentuale di memoria utilizzata, sulla quale si basa la soglia dell'avviso.

#!/usr/bin/env bash
# Extract memory figures from /proc/meminfo (values in kB)
MEM_TOTAL=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)
MEM_AVAIL=$(awk '/^MemAvailable:/ {print $2}' /proc/meminfo)

# Used memory percentage
MEM_USED_PCT=$(echo "scale=2; (1 - $MEM_AVAIL / $MEM_TOTAL) * 100" | bc)

echo "Total RAM : ${MEM_TOTAL} kB"
echo "Available : ${MEM_AVAIL} kB"
echo "Used      : ${MEM_USED_PCT}%"

Raccolta delle metriche di utilizzo del disco

Il comando df restituisce le informazioni sull'utilizzo dei filesystem. Per gli script, due opzioni sono essenziali:

  • -h — dimensioni leggibili dall'utente (solo per la visualizzazione; da evitare nei calcoli aritmetici)
  • --output=pcent,target — colonne analizzabili automaticamente (GNU coreutils)

Iterare su tutti i filesystem montati consente allo script di segnalare qualsiasi partizione quasi piena, non solo /. Il simbolo % viene rimosso con tr -d '%' prima del confronto tra interi.

#!/usr/bin/env bash
DISK_THRESHOLD=85

# Skip header line with tail -n +2
# --output=pcent,target gives "85% /var" style lines
df --output=pcent,target | tail -n +2 | while read -r USED_PCT MOUNT; do
    # Remove the % sign for arithmetic
    USED_INT=${USED_PCT//%/}

    if [ "$USED_INT" -ge "$DISK_THRESHOLD" ]; then
        echo "ALERT: Disk $MOUNT is ${USED_PCT} full"
    else
        echo "OK   : Disk $MOUNT is ${USED_PCT} full"
    fi
done

Output strutturato degli avvisi con marche temporali

I messaggi di avviso senza marche temporali sono quasi inutili nei file di log o nei report via email. Un prefisso coerente semplifica notevolmente l'analisi dei log con grep o con gli agenti di invio dei log.

Definisca una piccola funzione di avviso all'inizio dello script. La funzione antepone una marca temporale ISO-8601, un livello di gravità e il nome del controllo. Tutti gli avvisi vengono scritti sia su stdout sia in un file di log tramite tee.

  • date -u +"%Y-%m-%dT%H:%M:%SZ" — marca temporale UTC, indipendente dalla lingua
  • Scrivere su stderr per ALERT e su stdout per OK separa i segnali dal rumore nelle pipeline
#!/usr/bin/env bash
LOG_FILE="/var/log/healthcheck.log"

alert() {
    local LEVEL="$1"   # OK | WARN | ALERT
    local CHECK="$2"
    local MSG="$3"
    local TS
    TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
    local LINE="[$TS] [$LEVEL] [$CHECK] $MSG"

    if [ "$LEVEL" = "ALERT" ]; then
        echo "$LINE" | tee -a "$LOG_FILE" >&2
    else
        echo "$LINE" | tee -a "$LOG_FILE"
    fi
}

# Usage examples
alert "OK"    "DISK"  "/ is 42% full"
alert "ALERT" "DISK"  "/var is 91% full"

Invio di avvisi email con mail e sendmail

Il meccanismo più semplice per gli avvisi sul server è l'invio di email tramite l'MTA locale (postfix, sendmail o msmtp). Il comando mail (fornito da mailutils o bsd-mailx) compone e invia un messaggio con una sola riga.

  • -s — oggetto del messaggio
  • Invii il corpo tramite stdin
  • Sui server senza un MTA locale, sostituisca mail con una chiamata curl a un'API per l'invio transazionale di email

Protegga l'invio con un blocco di deduplicazione, in modo che una singola condizione rumorosa non inondi la casella di posta.

#!/usr/bin/env bash
ALERT_EMAIL="ops@example.com"
LOCK_DIR="/tmp/healthcheck_locks"
mkdir -p "$LOCK_DIR"

send_alert() {
    local CHECK="$1"
    local MSG="$2"
    local LOCK="$LOCK_DIR/${CHECK}.lock"

    # Only send if no lock exists (prevents repeated emails within the hour)
    if [ ! -f "$LOCK" ]; then
        echo "$MSG" | mail -s "[ALERT] $CHECK on $(hostname)" "$ALERT_EMAIL"
        touch "$LOCK"
        # Lock expires after 1 hour via cron or find+delete
        echo "Alert sent for $CHECK"
    else
        echo "Alert suppressed for $CHECK (lock active)"
    fi
}

send_alert "HIGH_LOAD" "Load average exceeded 80% on $(hostname) at $(date)"

Composizione dello script completo per il controllo dello stato

Ora combini tutti e tre i controlli — carico, memoria e disco — in un unico script coerente, con soglie configurabili all'inizio. Questo è il modello usato nell'automazione sysadmin in produzione:

  • Costanti dichiarate all'inizio, per poterle modificare facilmente senza intervenire sulla logica
  • Ogni controllo isolato in una funzione, per migliorare leggibilità e possibilità di eseguire unit test
  • Una funzione main coordina le chiamate
  • Codice di uscita 1 se viene generato almeno un avviso, 0 altrimenti — in questo modo lo script può essere integrato con framework di monitoraggio come Nagios/Icinga
#!/usr/bin/env bash
set -euo pipefail

# ── Thresholds ───────────────────────────────────────────
LOAD_THRESHOLD=80   # percent of CPU capacity
MEM_THRESHOLD=90    # percent used
DISK_THRESHOLD=85   # percent used
ALERT_EMAIL="ops@example.com"
LOG_FILE="/var/log/healthcheck.log"
ALERT_FIRED=0

# ── Helpers ──────────────────────────────────────────────
ts()    { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
log()   { echo "[$(ts)] $*" | tee -a "$LOG_FILE"; }
alert() { log "ALERT: $*"; echo "$*" | mail -s "[ALERT] $(hostname)" "$ALERT_EMAIL" 2>/dev/null; ALERT_FIRED=1; }

# ── Checks ───────────────────────────────────────────────
check_load() {
    local raw cores pct
    raw=$(cut -d' ' -f1 /proc/loadavg)
    cores=$(nproc)
    pct=$(echo "scale=2; $raw / $cores * 100" | bc)
    if [ "$(echo "$pct > $LOAD_THRESHOLD" | bc)" -eq 1 ]; then
        alert "Load ${pct}% exceeds ${LOAD_THRESHOLD}%"
    else
        log "OK load=${pct}%"
    fi
}

check_memory() {
    local total avail pct
    total=$(awk '/^MemTotal:/    {print $2}' /proc/meminfo)
    avail=$(awk '/^MemAvailable:/{print $2}' /proc/meminfo)
    pct=$(echo "scale=2; (1 - $avail / $total) * 100" | bc)
    if [ "$(echo "$pct > $MEM_THRESHOLD" | bc)" -eq 1 ]; then
        alert "Memory ${pct}% used (threshold ${MEM_THRESHOLD}%)"
    else
        log "OK memory=${pct}%"
    fi
}

check_disk() {
    df --output=pcent,target | tail -n +2 | while read -r used mnt; do
        local pct_int=${used//%/}
        if [ "$pct_int" -ge "$DISK_THRESHOLD" ]; then
            alert "Disk $mnt at ${used}"
        else
            log "OK disk $mnt=${used}"
        fi
    done
}

main() {
    log "=== Health check START ==="
    check_load
    check_memory
    check_disk
    log "=== Health check END (alerts=$ALERT_FIRED) ==="
    exit "$ALERT_FIRED"
}

main

Pianificazione con Cron

Uno script per il controllo dello stato è utile solo se viene eseguito automaticamente. cron è lo scheduler standard di Unix. Modifichi il crontab a livello di sistema oppure un file dedicato in /etc/cron.d/ per pianificare l'esecuzione dello script.

  • Esecuzione ogni 5 minuti: */5 * * * *
  • Utilizzi sempre percorsi assoluti in cron — $PATH è minimale nell'ambiente di cron
  • Reindirizzi l'output per impedire a cron di inviare un'e-mail a ogni esecuzione: >> /var/log/healthcheck.log 2>&1
  • Inserisca MAILTO="" all'inizio del crontab per disattivare le e-mail generate direttamente da cron
# /etc/cron.d/healthcheck
# Run the health check every 5 minutes as root
MAILTO=""
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

*/5 * * * * root /usr/local/sbin/healthcheck.sh >> /var/log/healthcheck.log 2>&1

Prevenzione delle raffiche di avvisi con i lock di cooldown

Quando una soglia viene superata continuamente, uno script ingenuo genera un avviso ogni 5 minuti — decine di e-mail prima che un tecnico possa intervenire. Un lock di cooldown sopprime gli avvisi ripetuti per un intervallo configurabile.

Il modello è il seguente: scrivere un file di lock al primo avviso; ignorare gli avvisi successivi finché il file è più recente del periodo di cooldown; find con -mmin controlla in modo atomico l'età del file senza dover eseguire calcoli sulle date.

#!/usr/bin/env bash
LOCK_DIR="/tmp/hc_locks"
COOLDOWN_MIN=60  # suppress repeat alerts for 60 minutes
mkdir -p "$LOCK_DIR"

should_alert() {
    local check="$1"
    local lock="$LOCK_DIR/${check}.lock"

    if [ ! -f "$lock" ]; then
        # No lock — allow alert and create lock
        touch "$lock"
        return 0  # true: send alert
    fi

    # Lock exists — check if it is older than the cooldown
    # find returns the filename only if it's OLDER than COOLDOWN_MIN
    local expired
    expired=$(find "$lock" -mmin +"$COOLDOWN_MIN" 2>/dev/null)

    if [ -n "$expired" ]; then
        touch "$lock"  # refresh lock timestamp
        return 0       # cooldown expired — allow alert
    fi

    return 1  # still within cooldown — suppress
}

# Usage
if should_alert "HIGH_LOAD"; then
    echo "Sending load alert..."
    # mail -s "..." ops@example.com <<< "Load too high"
else
    echo "Load alert suppressed (cooldown active)"
fi

Test e convalida dello script per il controllo dello stato

Prima della distribuzione, convalidi lo script in tre modi:

  • Controllo della sintassi: bash -n healthcheck.sh rileva gli errori di analisi senza eseguire lo script
  • Modalità trace: bash -x healthcheck.sh stampa ogni comando mentre viene eseguito — uno strumento prezioso per il debug
  • Sovrascrittura delle soglie: riduca temporaneamente le soglie quasi a zero, in modo che lo script generi avvisi su un host integro, verificando che il percorso degli avvisi funzioni dall'inizio alla fine

Per il percorso delle e-mail, durante i test reindirizzi mail verso un file di log utilizzando un flag MOCK_MAIL:

#!/usr/bin/env bash
# Smoke-test the alert path without sending real email
MOCK_MAIL=true
ALERT_EMAIL="ops@example.com"

send_mail() {
    local subject="$1"
    local body="$2"
    if [ "$MOCK_MAIL" = true ]; then
        echo "[MOCK MAIL] To: $ALERT_EMAIL | Subject: $subject"
        echo "[MOCK MAIL] Body: $body"
    else
        echo "$body" | mail -s "$subject" "$ALERT_EMAIL"
    fi
}

# Override threshold to guarantee an alert fires
LOAD_THRESHOLD=0   # Any load will exceed 0%
LOAD_RAW=$(cut -d' ' -f1 /proc/loadavg)
CPU_CORES=$(nproc)
PCT=$(echo "scale=2; $LOAD_RAW / $CPU_CORES * 100" | bc)

if [ "$(echo "$PCT > $LOAD_THRESHOLD" | bc)" -eq 1 ]; then
    send_mail "[ALERT] Load on $(hostname)" "Load is ${PCT}%"
fi

Verifica delle conoscenze: strategia di cooldown

Consideri il seguente scenario: il cron job per il controllo dello stato viene eseguito ogni 5 minuti. L'utilizzo del disco in /var supera l'85% e rimane oltre questa soglia per 3 ore. Vuole che il tecnico di reperibilità riceva un avviso una volta all'ora, non ogni 5 minuti. Quale strategia di implementazione è più appropriata?

Riepilogo della lezione: script per il controllo dello stato del sistema

In questa lezione ha creato una pipeline completa e pronta per la produzione per il controllo dello stato del sistema e la generazione di avvisi. Ecco i principi fondamentali da tenere a mente:

  • Fonte autorevole: legga le metriche da /proc/loadavg e /proc/meminfo — sono stabili, indipendenti dalla lingua e disponibili su ogni host Linux
  • Aritmetica in virgola mobile: utilizzi bc per confrontare le soglie in virgola mobile; il confronto tra interi di Bash (-gt) funziona solo con numeri interi
  • Iterazione sui dischi: utilizzi df --output=pcent,target per controllare ogni filesystem montato, non solo /
  • Logging strutturato: anteponga a ogni riga un timestamp UTC e un livello di gravità, così i log saranno facili da elaborare con grep e potranno essere inviati in modo affidabile ai sistemi di logging centralizzati
  • Lock di cooldown: i file di lock controllati con find -mmin impediscono le raffiche di avvisi senza modificare la pianificazione di cron
  • Componibilità: termini con il codice 1 quando viene generato un avviso, così lo script si integra con Nagios, Icinga o altri framework di monitoraggio
  • Test: utilizzi bash -n per i controlli della sintassi, bash -x per il debug tramite trace e un flag MOCK_MAIL per convalidare il percorso degli avvisi su host integri

Pianifichi lo script completato tramite /etc/cron.d/ e la sua infrastruttura controllerà continuamente se stessa, generando avvisi solo quando le soglie vengono superate in modo significativo.

Domande Frequenti

La lezione «Creare script per controlli e avvisi sullo stato del sistema» è gratuita?

Sì — il testo completo di «Creare script per controlli e avvisi sullo stato del sistema» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Linux Command Line & Bash Scripting Mastery, passa a CoddyKit PRO. Il corso Linux Command Line & Bash Scripting Mastery include 4 lezioni in totale.

Cosa imparerò in «Creare script per controlli e avvisi sullo stato del sistema»?

Raccolga metriche su carico, memoria e disco e attivi avvisi basati su soglie da script pianificati. Eserciti Linux Command Line & Bash Scripting Mastery con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Linux Command Line & Bash Scripting Mastery?

Non è richiesta alcuna esperienza precedente. Linux Command Line & Bash Scripting Mastery su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Creare script per controlli e avvisi sullo stato del sistema»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Linux Command Line & Bash Scripting Mastery?

Sì. Ogni lezione Linux Command Line & Bash Scripting Mastery include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Automatizzare la gestione di utenti e gruppi
  2. Controllare i servizi systemd e scrivere file unit
  3. Automatizzare dischi, filesystem e mount
  4. Creare script per controlli e avvisi sullo stato del sistema
← Torna a Linux Command Line & Bash Scripting Mastery