I colloqui per sistemisti Linux sono cambiati. Le domande di teoria, come "a cosa serve il comando X?", lasciano spazio a scenari concreti: un server che si comporta in modo anomalo e la richiesta di spiegare come si arriva alla causa. Tecmint ha raccolto dieci di questi casi. Sono utili per prepararsi a un colloquio, ma anche come checklist per chi gestisce server in produzione. Qui li riprendiamo con qualche nota di contesto.
1. File cancellato, ma il disco resta pieno
Un log da 6 GB viene eliminato con rm, ma df continua a segnalare il filesystem pieno.
Causa: rm rimuove la voce dalla directory, ma i blocchi dati restano allocati finché un processo tiene il file aperto. Un indizio è la differenza tra df -h /var e du -sh /var.
Diagnosi: sudo lsof +L1 elenca i file con link count zero (cancellati) ancora aperti da un processo.
Soluzione: riavviare il servizio, oppure azzerare il file tramite il suo file descriptor (identificativo numerico con cui un processo accede a un file aperto):
sudo truncate -s 0 /proc/<PID>/fd/<FD>
Prevenzione: sui log attivi usare truncate -s 0 invece di rm, e configurare logrotate con copytruncate o con il reload del servizio.
2. "No space left on device" con disco al 45%
Causa: esaurimento degli inode, le strutture che descrivono ogni file nel filesystem. Milioni di file piccolissimi, come sessioni PHP o cache, possono esaurirli prima dello spazio.
Diagnosi:
df -i /
sudo du --inodes -x -d 4 / 2>/dev/null | sort -rn | head
Soluzione: cancellare con find, che evita i limiti di espansione della shell:
sudo find /var/lib/php/sessions -type f -mtime +7 -delete
Nota: XFS, default su RHEL, alloca gli inode dinamicamente. ext4, default su Debian e Ubuntu, ne ha un numero fisso deciso alla creazione del filesystem.
3. Il servizio funziona a mano ma non al boot
Causa: il servizio non è abilitato oppure parte prima che la rete sia pronta.
Diagnosi: systemctl is-enabled myapp, journalctl -b -u myapp per i log del boot corrente e journalctl --list-boots per confrontarli con i boot precedenti.
Soluzione: un drop-in systemd (file che sovrascrive parti di una unit senza modificare l'originale) in /etc/systemd/system/myapp.service.d/override.conf:
[Unit]
Wants=network-online.target
After=network-online.target
Poi sudo systemctl daemon-reload && sudo systemctl enable --now myapp.
4. Il ping all'IP funziona, quello al nome no
Se ping 8.8.8.8 risponde e ping google.com no, la rete funziona ma il DNS è rotto.
Diagnosi: controllare /etc/resolv.conf su RHEL, oppure resolvectl status <interfaccia> su Ubuntu con systemd-resolved, e interrogare direttamente il server DNS con dig @192.168.122.1 google.com +short.
Soluzione su RHEL con NetworkManager:
sudo nmcli connection modify enp1s0 ipv4.dns "192.168.122.1" ipv4.ignore-auto-dns yes
sudo nmcli connection up enp1s0
Modificare a mano /etc/resolv.conf è inutile se il file è gestito da NetworkManager o systemd-resolved: verrà sovrascritto.
5. Il web server risponde solo su localhost
Causa: il servizio è in ascolto su 127.0.0.1 invece che su tutte le interfacce, oppure il firewall blocca la porta.
Diagnosi: sudo ss -tlnp | grep ':80' mostra l'indirizzo e il processo in ascolto.
Soluzione: correggere la direttiva in listen 80;, verificare con sudo nginx -t e ricaricare. Su RHEL aprire il firewall:
sudo firewall-cmd --permanent --add-service=http && sudo firewall-cmd --reload
6. Login SSH lento di 20-30 secondi
Causa: tentativi di autenticazione GSSAPI (meccanismo usato soprattutto con Kerberos) o reverse DNS lookup lato server che vanno in timeout.
Diagnosi: ssh -v utente@host mostra dove si blocca la connessione. ssh -o GSSAPIAuthentication=no conferma il sospetto e sudo sshd -T | grep -i usedns mostra la configurazione effettiva.
Soluzione: un file in /etc/ssh/sshd_config.d/ con:
UseDNS no
GSSAPIAuthentication no
Verificare con sudo sshd -t prima di riavviare il servizio (sshd su RHEL, ssh su Ubuntu). È un'abitudine che evita di chiudersi fuori da un server remoto.
7. Load average alto, CPU ferme
Load 12 su un server a 4 core, ma la CPU è quasi inattiva.
Causa: su Linux il load average conta anche i processi in stato D (uninterruptible sleep), bloccati in attesa di I/O su disco o rete. Il collo di bottiglia è lo storage, non la CPU.
Diagnosi:
uptime; nproc
vmstat 1 5 # colonne b (processi bloccati) e wa (I/O wait)
ps -eo state,pid,user,comm | awk '$1 == "D"'
iostat -x 2 3 # dal pacchetto sysstat
Un dispositivo con %util vicino al 100% e valori alti di r_await/w_await è il colpevole. Su cloud, spesso significa che si è superato il limite di IOPS del volume.
8. "Permission denied (publickey)"
La chiave pubblica è in authorized_keys, ma SSH rifiuta l'accesso.
Causa: permessi troppo aperti, chiave spezzata su più righe o contesto SELinux errato.
Diagnosi: ssh -v -i ~/.ssh/id_ed25519 utente@host lato client e journalctl -u sshd -n 20 (o -u ssh) lato server, dove di solito il motivo è scritto chiaramente.
Soluzione:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod go-w ~
restorecon -Rv ~/.ssh # su sistemi con SELinux
9. Nginx restituisce 403 nonostante i permessi corretti
Il sito viene spostato in /srv/www, proprietario e permessi sono corretti, ma Nginx risponde 403 Forbidden.
Causa (RHEL e derivate): SELinux, il sistema di controllo degli accessi obbligatorio del kernel, impedisce al web server di leggere file con un contesto non adatto.
Diagnosi: getenforce, ls -Z /srv/www/index.html e sudo ausearch -m AVC -ts recent per vedere i dinieghi registrati.
Soluzione:
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
sudo restorecon -Rv /srv/www
La tentazione di disabilitare SELinux è comune, ma è la risposta sbagliata, sia al colloquio sia in produzione.
10. Il processo muore senza lasciare log
L'applicazione si chiude ogni pochi giorni, nessuno l'ha riavviata e i log applicativi sono vuoti.
Causa: l'OOM killer, il meccanismo del kernel che termina i processi quando la memoria si esaurisce.
Diagnosi: systemctl status myapp mostra code=killed, status=9, poi:
sudo dmesg -T | grep -iE "out of memory|oom-kill"
sudo journalctl -k | grep -i "out of memory"
Soluzione: limitare la memoria del servizio e gestirne il riavvio con un drop-in:
[Service]
MemoryMax=2G
Restart=on-failure
RestartSec=5
Il limite basato sui cgroup fa sì che sia il servizio a essere terminato e riavviato in modo controllato, invece di mettere in crisi l'intero sistema. Verifica con systemctl show myapp -p MemoryMax.
Il metodo conta più dei comandi
Il filo comune dei dieci scenari è un metodo, non una lista di comandi da memorizzare: confrontare due misure che dovrebbero coincidere (df e du, load e CPU), leggere i log del momento giusto (boot, kernel, audit), verificare cosa è in ascolto e dove, e chiedersi sempre chi ha fatto cosa a un processo.
Molti di questi problemi si ripresentano identici anche su Kubernetes. Un container terminato con OOMKilled è lo scenario 10 visto attraverso i cgroup del Pod. Un Pod che risolve gli IP ma non i nomi è lo scenario 4 applicato a CoreDNS. Un servizio raggiungibile solo dall'interno del Pod è lo scenario 5. Chi conosce bene Linux parte avvantaggiato anche nel troubleshooting dei cluster.
