Skip to main content

Module 1 · Filesystem & Permissions

FHS Hierarchy

  • Lesson 1/15
  • 30 min
  • Difficulty: Basic

This lesson is not available in English yet: you are reading it in Italian.

Objective

Decidere in quale cartella del filesystem va un file nuovo, e verificare con un comando se una voce della radice e' cartella, collegamento o punto di montaggio

Prerequisites

No prerequisites: you can start here.

Prima di leggere: prova a rispondere

Hai un server Linux appena consegnato e devi sistemare tre cose: il file di configurazione del tuo servizio, il database che quel servizio scrive, e un archivio temporaneo che serve solo durante l'installazione. Scrivi su un foglio dove metti ciascuno dei tre, e perché. Non cercare la risposta: scrivila a memoria, anche se sei incerto.

La domanda sembra banale e non lo è. La maggior parte dei guasti che ho dovuto diagnosticare su un server altrui nasceva da un file messo nel posto sbagliato: una configurazione sotto /usr cancellata dall'aggiornamento del pacchetto, un database sotto /tmp svuotato al riavvio, un archivio da due gigabyte dentro /etc che faceva fallire il backup della configurazione. Nessuno di quei tre errori produce un messaggio chiaro. Producono un sistema che funziona finché non smette, in un momento che non controlli tu.

Il problema: la cartella sbagliata non dà errore

Linux non ti impedisce di scrivere un file dove vuoi. Se hai i permessi, il file ci va, e tutto sembra a posto. La gerarchia delle cartelle non è un vincolo tecnico imposto dal kernel: è una convenzione che il sistema di pacchetti, gli strumenti di backup, gli aggiornamenti e i tuoi colleghi danno per scontata. Chi la rompe non viene fermato. Viene punito più tardi.

La convenzione ha un nome e un documento. La pagina di manuale hier(7) presente su questo sistema, nella sezione STANDARDS, rimanda al Filesystem Hierarchy Standard versione 3.0, pubblicato il 19 marzo 2015. La stessa pagina, nella sezione BUGS, dice una cosa che vale la pena leggere per intero: «This list is not exhaustive; different distributions and systems may be configured differently». Quindi lo standard esiste, ma la tua distribuzione può discostarsene, e il modo di sapere come stanno le cose sulla tua macchina è guardarla.

Non memorizzare l'elenco: memorizza la domanda

Imparare la gerarchia a memoria funziona male, perché l'elenco è lungo e in parte storico. Funziona molto meglio ricordare, per ogni cartella, a quale domanda risponde. Le domande sono due, e si incrociano: il contenuto cambia nel tempo o è fisso? Il contenuto è specifico di questa macchina o sarebbe identico su mille macchine uguali?

Da quell'incrocio nascono le quattro cartelle che userai ogni giorno. /usr contiene quello che è fisso e condivisibile: i programmi installati dai pacchetti. /etc contiene quello che è fisso e specifico di questa macchina: la configurazione. /var contiene quello che cambia e sopravvive al riavvio: log, database, cache, code di posta. /tmp contiene quello che cambia e non deve sopravvivere.

La pagina hier(7) lo dice con le sue parole. Su /etc: «Contains configuration files which are local to the machine». Su /usr: «It should hold only shareable, read-only data, so that it can be mounted by various machines running Linux». Su /tmp: «This directory contains temporary files which may be deleted with no notice, such as by a regular job or at system boot up». Quel «with no notice» è la ragione per cui un database sotto /tmp è una bomba a orologeria.

Due cartelle che non contengono file

/proc e /sys sembrano cartelle e non lo sono. Sono due finestre sul kernel, montate come filesystem separati, e i loro contenuti vengono generati nel momento in cui li leggi. Si vede dal fatto che dichiarano dimensione zero pur avendo contenuto.

$ ls -l /proc/cpuinfo /proc/meminfo
-r--r--r-- 1 root root 0 Oct 30 10:51 /proc/cpuinfo
-r--r--r-- 1 root root 0 Oct 30 10:51 /proc/meminfo

Dimensione zero, e però cat /proc/meminfo stampa decine di righe. Il kernel non tiene quei byte su disco: li produce quando qualcuno apre il file. È il motivo per cui nessuno strumento di backup copia /proc, e per cui una copia di /proc non servirebbe a niente.

La prova che sono filesystem a sé sta in findmnt. Questo è l'output misurato sulla mia macchina il 2026-10-30, e la prima riga dipende dal tuo disco:

$ for m in / /proc /sys /run /tmp; do findmnt -n -o TARGET,SOURCE,FSTYPE "$m"; done
/ /dev/nvme0n1p2 ext4
/proc proc proc
/sys sysfs sysfs
/run tmpfs tmpfs
/tmp tmpfs tmpfs

Qui /tmp è un tmpfs, cioè vive in memoria e svanisce al riavvio per costruzione. Su molti server /tmp è invece una cartella normale sul disco di root, e viene ripulita da un lavoro periodico. Le due configurazioni si comportano in modo diverso sotto pressione di memoria e con i file grandi, quindi la domanda «com'è /tmp qui?» va fatta a ogni macchina nuova, con il comando sopra.

Esempio svolto: perché /bin è una bugia gentile

Il problema di partenza: un collega ti dice che i comandi di base stanno in /bin e quelli amministrativi in /sbin. Vuoi sapere se è ancora vero sulla tua macchina.

L'informazione che hai: le due cartelle esistono, perché compaiono nell'elenco della radice. Il ragionamento: se fossero cartelle vere, ls -ld mostrerebbe una d come primo carattere dei permessi. Se fossero collegamenti, mostrerebbe una l e la destinazione. Quindi la domanda si decide con un comando, non con un'opinione.

$ ls -ld /bin /lib /sbin
lrwxrwxrwx 1 root root 7 Apr 22  2024 /bin -> usr/bin
lrwxrwxrwx 1 root root 7 Apr 22  2024 /lib -> usr/lib
lrwxrwxrwx 1 root root 8 Apr 22  2024 /sbin -> usr/sbin

Tutte e tre sono collegamenti simbolici, non cartelle. Su questa macchina i file stanno sotto /usr e le vecchie posizioni sopravvivono solo come scorciatoie, per non rompere gli script che le citano. La decisione che prendo di conseguenza: nei miei script scrivo /usr/bin/bash e non /bin/bash, perché il primo è il percorso reale e il secondo dipende da un collegamento che una distribuzione futura potrebbe togliere.

L'alternativa che ho considerato e scartato: continuare a scrivere /bin/bash perché «funziona da sempre». Funziona, ma funziona per una ragione che non è documentata come garanzia, ed è il tipo di dipendenza implicita che rompe un deploy in un momento scelto da qualcun altro.

La verifica: readlink -f /bin/bash mostra il percorso finale dopo aver seguito tutti i collegamenti, e se i due percorsi coincidono hai la conferma. L'errore che avrei potuto commettere è leggere l'output di ls -l senza guardare il primo carattere, e concludere che /bin è una cartella perché il nome compare nell'elenco della radice. Il nome compare sempre: è il tipo che cambia.

Esercizio 1, guidato: classifica quattro file

Per ciascuno di questi quattro file, scegli la cartella e scrivi la domanda a cui hai risposto per scegliere. Il primo è già fatto come modello.

  1. portfolio-backend.service, la descrizione del servizio per systemd. Risposta: /etc/systemd/system/, perché è configurazione fissa e specifica di questa macchina.
  2. portfolio.log, dove il servizio scrive una riga per ogni richiesta.
  3. backend.jar, il programma compilato che il servizio esegue.
  4. Un archivio di 200 MB scaricato per estrarre un file e poi buttato.

Esercizio 2, autonomo: misura la tua radice

Esegui ls -1 / sulla tua macchina e confronta l'elenco con quello che hai appena letto. Per ogni voce che non compare in hier(7), scopri chi l'ha creata. Criterio di successo: per almeno una voce estranea sai dire quale programma o quale scelta di installazione l'ha messa lì, e lo hai verificato con un comando, non dedotto dal nome.

Il comando che ti serve per la verifica lo conosci già in parte: findmnt ti dice se una voce è un punto di montaggio, e ls -ld ti dice se è un collegamento. Se non è nessuna delle due, è una cartella normale e devi cercare chi la popola.

Soluzioni commentate

Esercizio 1, voce 2 (portfolio.log). Va sotto /var/log/. La domanda è: il contenuto cambia nel tempo? Sì, cresce a ogni richiesta. Sopravvive al riavvio? Sì, altrimenti perderesti la traccia dell'incidente che ha causato il riavvio. Quell'incrocio è esattamente /var. L'alternativa /tmp è sbagliata perché hier(7) autorizza la cancellazione senza preavviso, e un log che sparisce quando serve non è un log. L'alternativa /etc è sbagliata in modo più sottile: funzionerebbe per settimane, poi il file crescerebbe e il backup della configurazione, che di solito è piccolo e frequente, diventerebbe lento e pesante senza una causa evidente.

Voce 3 (backend.jar). Qui la risposta corretta dipende da chi lo installa, e questa è la parte interessante. Se arriva da un pacchetto della distribuzione va sotto /usr, perché è dato fisso e condivisibile. Se lo installi tu a mano, fuori dal gestore di pacchetti, la cartella giusta è /opt: hier(7) la descrive come il posto dei pacchetti aggiuntivi. Mettere un file installato a mano sotto /usr non dà errore subito, ma lo mette in una zona che il gestore di pacchetti considera sua, e un aggiornamento può sovrascriverlo o cancellarlo.

Voce 4 (l'archivio da 200 MB). Va in /tmp, e la ragione è la stessa che rende /tmp pericoloso per il database: la cancellazione senza preavviso. Qui la vuoi. Una cautela misurata: se findmnt /tmp ti dice tmpfs, quei 200 MB occupano memoria, non disco. Su una macchina con poca RAM conviene /var/tmp, che hier(7) destina ai file temporanei che devono sopravvivere al riavvio e che di norma sta sul disco.

Esercizio 2. Sulla mia macchina l'elenco di / contiene snap, cdrom, lost+found e due file di swap, nessuno dei quali è in hier(7). snap è creata dal gestore di pacchetti omonimo; lost+found è creata da ext4 alla formattazione e ospita i file recuperati da un controllo di coerenza; i file di swap sono una mia scelta di configurazione. Il ragionamento che conta non è quale sia la risposta sulla mia macchina, ma che ogni voce estranea ha un responsabile: una radice con una cartella di cui nessuno sa rendere conto è una radice in cui qualcuno ha scritto senza dirlo.

Domande per fissare il concetto

Rispondi a voce, come se spiegassi a un collega che arriva da Windows. In quale situazione mettere un file sotto /usr invece che sotto /opt causerebbe un danno concreto, e chi sarebbe l'autore del danno? Se /var finisse lo spazio, quali servizi si fermerebbero per primi e perché? E perché il fatto che /proc/meminfo dichiari dimensione zero non è un difetto ma una conseguenza necessaria di come è fatto?

Se su una delle tre esiti, non rileggere: riapri man 7 hier e cerca la voce che ti serve. Il gesto di cercare nella fonte è parte della competenza, e vale più del ricordo dell'elenco.

Che cosa adesso sai fare

Sai decidere in quale cartella va un file nuovo rispondendo a due domande, invece di ricordare un elenco. Sai stabilire con un comando se una voce della radice è una cartella, un collegamento o un punto di montaggio, e sai che su questa famiglia di distribuzioni /bin e /sbin sono collegamenti verso /usr. Sai riconoscere che /proc e /sys non contengono file su disco, e sai perché dichiarano dimensione zero.

La verifica concreta che puoi fare adesso: prendi un servizio qualsiasi installato sulla tua macchina e trova i suoi quattro pezzi, il programma, la configurazione, i dati e i log, ciascuno nella sua cartella. Se li trovi tutti e quattro al posto giusto, hai capito la gerarchia. Se uno è fuori posto, hai trovato il primo debito tecnico di quella macchina.