惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
L
LangChain Blog
aimingoo的专栏
aimingoo的专栏
IT之家
IT之家
B
Blog
博客园_首页
博客园 - 司徒正美
有赞技术团队
有赞技术团队
博客园 - 聂微东
I
InfoQ
美团技术团队
GbyAI
GbyAI
阮一峰的网络日志
阮一峰的网络日志
H
Help Net Security
大猫的无限游戏
大猫的无限游戏
MyScale Blog
MyScale Blog
WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
A
About on SuperTechFans
人人都是产品经理
人人都是产品经理
Microsoft Azure Blog
Microsoft Azure Blog
Engineering at Meta
Engineering at Meta
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Cloudflare Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Watchdog Apache con Bash, Cron e Systemd: monitoraggio au...
minnogit · 2026-05-18 · via DEV Community

minnogit

In alcuni scenari ad alto carico o in presenza di problemi lato backend, Apache può degradare progressivamente fino a diventare lento, saturare le risorse o smettere di rispondere correttamente.

Per mitigare questo tipo di problemi è possibile implementare un watchdog leggero in Bash che:

  • monitora periodicamente lo stato del sistema;
  • verifica alcune metriche critiche;
  • esegue automaticamente un reload o un restart di Apache;
  • registra gli eventi tramite syslog e journalctl.

Questo approccio è particolarmente utile in ambienti:

  • con reverse proxy Apache;
  • con backend applicativi instabili;
  • con leak di connessioni;
  • dove è necessario un meccanismo di self-healing semplice e trasparente.

Obiettivo dello script

Lo script controlla:

  1. RAM disponibile;
  2. numero di PID usati dal servizio Apache;
  3. connessioni TCP in stato close-wait verso un backend specifico;
  4. health check HTTP locale;

In base alle soglie configurate:

  • esegue un reload di Apache;
  • oppure un restart completo;
  • scrive i dettagli nel journal di systemd.

Script completo

#!/bin/bash

# --- PARAMETRI DI SOGLIA ---
SOGLIA_RAM_FREE_MB=100
SOGLIA_PIDS_PERCENT=60
SOGLIA_close-wait=300

# --- RACCOLTA DATI ---
# Usiamo percorsi assoluti per cron e variabili pulite
RAM_DISPONIBILE_MB=$(/usr/bin/free -m | grep Mem | awk '{print $7}')

# Conteggio in tempo reale delle connessioni orfane in close-wait
close-wait_COUNT=$(/usr/bin/ss -H -tanp state close-wait | /usr/bin/wc -l)

# Gestione PIDs con controllo esistenza file (evita errori se Apache è spento)
PIDS_FILE="/sys/fs/cgroup/system.slice/apache2.service/pids.current"
MAX_FILE="/sys/fs/cgroup/system.slice/apache2.service/pids.max"

if [ -f "$PIDS_FILE" ]; then
    CURRENT_APACHE_PIDS=$(cat "$PIDS_FILE")
    MAX_APACHE_PIDS=$(cat "$MAX_FILE")

    # Se MAX è la stringa "max", o è 0, o è vuoto -> la percentuale è 0 (limite infinito)
    if [ "$MAX_APACHE_PIDS" = "max" ] || [ -z "$MAX_APACHE_PIDS" ] || [ "$MAX_APACHE_PIDS" -eq 0 ] 2>/dev/null; then
        PERCENTUAL_PIDS=0
    else
        PERCENTUAL_PIDS=$(( 100 * CURRENT_APACHE_PIDS / MAX_APACHE_PIDS ))
    fi
else
    PERCENTUAL_PIDS=0
fi

# --- LOGICA DI CONTROLLO ---
AZIONE_NECESSARIA=false
TIPO_AZIONE="reload" # Default

if [ "$RAM_DISPONIBILE_MB" -lt "$SOGLIA_RAM_FREE_MB" ]; then
    MOTIVO="RAM bassa (${RAM_DISPONIBILE_MB}MB)"
    AZIONE_NECESSARIA=true
    TIPO_AZIONE="restart" # Se la RAM è finita, il reload è troppo lento
elif [ "$PERCENTUAL_PIDS" -gt "$SOGLIA_PIDS_PERCENT" ]; then
    MOTIVO="PIDs al ${PERCENTUAL_PIDS}% (${CURRENT_APACHE_PIDS}/${MAX_APACHE_PIDS})"
    AZIONE_NECESSARIA=true
    TIPO_AZIONE="reload"
elif [ "$close-wait_COUNT" -gt "$SOGLIA_close-wait" ]; then
    MOTIVO="Rilevato leak di socket (${close-wait_COUNT} connessioni in close-wait)"
    AZIONE_NECESSARIA=true
    TIPO_AZIONE="reload" # Il reload è sufficiente a liberare i socket orfani
fi

# Check sopravvivenza: se Apache non risponde, forza RESTART a prescindere dalle soglie
if ! /usr/bin/curl -s --max-time 5 http://127.0.0.1/ > /dev/null; then
    MOTIVO="Apache non risponde (Health Check fallito)"
    AZIONE_NECESSARIA=true
    TIPO_AZIONE="restart"
fi

# --- AZIONE ---
if $AZIONE_NECESSARIA; then
    echo "$(date): Allarme: ${MOTIVO}. Eseguo ${TIPO_AZIONE}."
    /usr/bin/logger -t apache_health_watchdog "Allarme: ${MOTIVO}. Eseguo ${TIPO_AZIONE}."

    if [ "$TIPO_AZIONE" == "reload" ]; then
        /usr/bin/systemctl reload apache2

        # Se il reload fallisce (es. kernel già in fork rejected), prova il restart
        if [ $? -ne 0 ]; then
            /usr/bin/logger -t apache_health_watchdog "Reload fallito, forzo restart."
            /usr/bin/systemctl restart apache2
        fi
    else
        /usr/bin/systemctl restart apache2
    fi
fi

Enter fullscreen mode Exit fullscreen mode


Installazione

Salvare lo script in:

/usr/local/sbin/check_system_health.sh

Enter fullscreen mode Exit fullscreen mode

Rendere il file eseguibile:

chmod +x /usr/local/sbin/check_system_health.sh

Enter fullscreen mode Exit fullscreen mode


Configurazione del cron

Aggiungere in /etc/crontab:

*/2 * * * * root flock -n /tmp/apache_watchdog.lock /usr/local/sbin/check_system_health.sh >> /var/log/apache_health_watchdog.log 2>&1

Enter fullscreen mode Exit fullscreen mode

Questo esegue il controllo ogni 2 minuti.

Perché usare flock

flock evita esecuzioni concorrenti dello script.

In condizioni di degrado del sistema:

  • un controllo potrebbe impiegare più tempo del previsto;
  • il cron successivo potrebbe partire mentre il precedente è ancora attivo;
  • si rischiano reload o restart multipli contemporanei.

Con:

flock -n /tmp/apache_watchdog.lock

Enter fullscreen mode Exit fullscreen mode

solo una istanza dello script può essere eseguita alla volta.


Analisi delle metriche monitorate

1. RAM disponibile

free -m

Enter fullscreen mode Exit fullscreen mode

Lo script utilizza:

awk '{print $7}'

Enter fullscreen mode Exit fullscreen mode

che corrisponde alla colonna available.

Se la memoria disponibile scende sotto:

SOGLIA_RAM_FREE_MB=100

Enter fullscreen mode Exit fullscreen mode

viene eseguito un restart completo di Apache.

Questo è utile perché:

  • il reload può richiedere fork aggiuntivi;
  • in condizioni di memoria critica il reload potrebbe peggiorare la situazione;
  • un restart libera immediatamente worker e memoria frammentata.

2. Saturazione PID Apache

Lo script legge direttamente i contatori cgroup di systemd:

/sys/fs/cgroup/system.slice/apache2.service/pids.current

Enter fullscreen mode Exit fullscreen mode

e:

/sys/fs/cgroup/system.slice/apache2.service/pids.max

Enter fullscreen mode Exit fullscreen mode

Questo approccio è molto più affidabile rispetto al parsing di ps.

Se il servizio supera:

SOGLIA_PIDS_PERCENT=60

Enter fullscreen mode Exit fullscreen mode

viene eseguito un reload.

Questo permette di:

  • rigenerare worker;
  • liberare processi stuck;
  • evitare il raggiungimento del limite massimo PID.

3. Socket close-wait

Lo stato close-wait indica:

  • il peer remoto ha chiuso la connessione;
  • il processo locale non ha ancora rilasciato il socket.

Molte connessioni in close-wait possono indicare:

  • leak applicativi;
  • backend instabili;
  • worker Apache bloccati;
  • timeout mal configurati.

Lo script utilizza:

ss -tanp state close-wait

Enter fullscreen mode Exit fullscreen mode

Questo approccio è preferibile rispetto a netstat perché:

  • ss è più moderno;
  • usa meno CPU;
  • legge direttamente dal kernel tramite netlink;
  • è più affidabile sotto alto carico;
  • evita dipendenze da net-tools.

Se il numero supera:

SOGLIA_close-wait=300

Enter fullscreen mode Exit fullscreen mode

viene eseguito un reload.


Logging e monitoraggio

Lo script utilizza:

logger -t apache_health_watchdog

Enter fullscreen mode Exit fullscreen mode

Quindi gli eventi sono consultabili tramite:

journalctl -t apache_health_watchdog

Enter fullscreen mode Exit fullscreen mode

Esempio:

May 18 10:42:01 server apache_health_watchdog: Allarme: Rilevato leak di socket (182 connessioni in close-wait). Eseguo reload.

Enter fullscreen mode Exit fullscreen mode

Per seguire i log in tempo reale:

journalctl -f -t apache_health_watchdog

Enter fullscreen mode Exit fullscreen mode


Quando usare questo approccio

Questo watchdog è particolarmente utile quando:

  • Apache funge da reverse proxy;
  • i backend possono bloccarsi o degradare;
  • non è disponibile un orchestratore avanzato;
  • si vuole una soluzione semplice e immediata;
  • si desidera un meccanismo di self-healing leggero.

Limiti della soluzione

Questo approccio non sostituisce:

  • un monitoraggio completo;
  • metriche Prometheus/Grafana;
  • tracing applicativo;
  • analisi root cause;
  • tuning corretto di Apache e backend.

Il watchdog serve principalmente come:

  • mitigazione automatica;
  • protezione operativa;
  • recovery rapido.