Un link non è una scorciatoia come su Windows, e la differenza fra le due specie di link si spiega in una riga: decide se domani il collegamento funzionerà ancora, o punterà al file sbagliato senza dirtelo.
Il nome non è il file: l’inode
Su un filesystem Linux i metadati di un file — permessi, proprietario, dimensione, elenco dei blocchi occupati — stanno in una struttura chiamata inode. Il nome che vedi dentro una directory è soltanto una voce che punta a un inode. Da qui discende tutto il resto.
$ ls -li
3806696 -rw-r--r-- 2 carol carol 111702 Jun 7 10:13 hardlink
3806696 -rw-r--r-- 2 carol carol 111702 Jun 7 10:13 target.txt
L’opzione -i mostra il numero di inode nella prima colonna: qui i due nomi hanno lo stesso numero, quindi sono lo stesso file. La colonna subito dopo i permessi è il contatore dei link, cioè quanti nomi puntano a quell’inode. ls -li è una combinazione da ricordare a memoria: è l’unico modo rapido per capire se due file sono in realtà uno solo.
Hard link: un secondo nome, non una copia
Il comando è ln bersaglio nome_del_link: prima il bersaglio, che deve già esistere, poi il nome nuovo. L’ordine è controintuitivo la prima volta e va fissato. Se ometti il secondo argomento, il link nasce nella directory corrente con lo stesso nome del bersaglio.
$ ln ricette.txt receitas.txt
$ ln ricette.txt /home/carol/Documenti/copia
Ogni hard link fa salire il contatore di uno. Un file normale parte da 1; una directory parte da 2, perché è nominata dalla directory padre e dal proprio ., e sale di uno per ogni sottodirectory, per via del .. che ci sta dentro.
Cancellare un nome non cancella i dati: finché il contatore non arriva a zero il file continua a esistere. E non c’è un originale e una copia — i nomi sono pari fra loro, e guardando il filesystem non puoi dire quale sia nato prima.
Due limiti da ricordare, perché sono esattamente le domande d’esame:
- un hard link non può attraversare i filesystem. Se ci provi, per esempio verso una chiavetta montata, ottieni
Invalid cross-device link: il numero di inode ha senso solo dentro il suo filesystem; - un hard link non si può creare su una directory. Lo fa solo il kernel, per le voci
.e...
Link simbolici: un percorso scritto dentro un file
Il comando è lo stesso con l’aggiunta di -s: ln -s bersaglio nome_del_link. Un link simbolico è un piccolo file che contiene un percorso, e non ha nessuno dei due limiti visti sopra: può puntare a una directory, a un altro filesystem, perfino a un bersaglio che non esiste ancora.
$ ln -s target.txt softlink
$ ls -lh
-rw-r--r-- 1 carol carol 110K Jun 7 10:13 target.txt
lrwxrwxrwx 1 carol carol 12 Jun 7 10:14 softlink -> target.txt
Si riconosce da tre cose: la l come primo carattere, la freccia con il bersaglio, e i permessi che sono sempre lrwxrwxrwx. Quei permessi non contano nulla, valgono quelli del bersaglio. Anche la dimensione inganna: sono i byte del percorso scritto dentro il link.
Perché i simbolici si rompono e i fisici no
L’hard link punta a un inode, quindi non si rompe: puoi spostarlo, rinominarlo, cancellare l’altro nome. Il link simbolico punta a un nome, e un nome può cambiare significato.
Se scrivi il bersaglio senza percorso, viene interpretato come relativo alla directory in cui si trova il link:
$ ln -s clienti.txt partner.txt
$ mv partner.txt ..
$ less ../partner.txt
../partner.txt: No such file or directory
Il caso davvero cattivo però è un altro: se nella nuova directory esiste per caso un altro file chiamato clienti.txt, il link non si rompe e punta a quel file lì, in silenzio. Regola pratica: se link e bersaglio non restano nella stessa directory, scrivi il percorso assoluto del bersaglio.
Il link si rompe anche se il bersaglio viene cancellato o rinominato. Per trovare i link rotti c’è find . -xtype l, e ls --color di solito li mostra in rosso lampeggiante.
Altre due trappole pratiche. rm link cancella il link, ma rm -r link/ con la barra finale segue il link e ti svuota la directory di destinazione. E per sostituire un link che punta a una directory serve ln -sfn nuovo_bersaglio link: senza -n, ln -sf entra nella directory puntata e crea il link dentro di essa.
Copiare o linkare, e a cosa servono in pratica
Una copia fatta con cp occupa spazio suo ed è indipendente: modifichi l’una e l’altra resta com’era. Un hard link non occupa spazio a parte la voce di directory, e i due nomi mostrano sempre lo stesso contenuto perché sono lo stesso contenuto. Attenzione che cp di default segue i link simbolici e ne copia il bersaglio: per copiare i link come link servono cp -d oppure cp -a.
L’amministrazione di sistema è piena di link simbolici, e riconoscerli fa risparmiare tempo: /usr/bin/vi che punta a vim, il sistema delle alternative di Debian sotto /etc/alternatives/, i link in /etc/rc5.d/ verso /etc/init.d/ sui sistemi SysVinit, e quelli che systemctl enable crea in /etc/systemd/system/multi-user.target.wants/ sui sistemi systemd. È sempre lo stesso meccanismo: cambiare a cosa punta un nome, senza spostare un solo byte di dati.