Guida Linux: il filesystem (parte II)I permessi di accesso sui filePer visualizzare a video l'elenco dei file contenuti all'interno di una directory occorre usare il comando ls. Infatti ls sta per list (elenca). Il comando ls accetta varie opzioni come -a, -l o -i. L'opzione -l (l sta per long, cioe' lunga, estesa) permette di visualizzare alcuni dettagli importanti di ciascun file. Percio' il comando ls da solo visualizza l'elenco dei file di una directory ma usato con l'opzione -l visualizza alcuni importanti dettagli. Ad esempio:
ls -l Il nome del file e' l'ultima informazione presente in ogni riga. Cosa significano allora tutte le altre informazioni? Il primo carattere indica il tipo di file e puo' essere un trattino o una 'd'. Il trattino indica un comune file, mentre la 'd' indica che si tratta di una directory. In realta' i tipi di file possibili sono 8:
- file regolare Gli altri 9 caratteri indicano i permessi di accesso al file. Segue il numero di link, il nome del proprietario del file, il nome del gruppo a cui appartiene il proprietario, le dimensioni in byte, la data e l'ora dell'ultima modifica ed infine il nome del file stesso. Nell'esempio precedente il file 'file4' e' lungo 210 byte (210 caratteri) e' stato modificato il 18 febbraio alle ore 12:10. Il suo proprietario e' mau che appartiene al gruppo utenti. Questo file ha un unico link e non e' una directory ma un comune file. Qualsiasi file puo' essere acceduto o meno da 3 categorie di utenti: il proprietario del file, il gruppo di utenti a cui appartiene il proprietario ed infine tutti gli altri utenti che posseggono un account sul sistema. Un file puo' essere letto o visualizzato se ne si possiede il permesso in lettura; puo' essere sovrascritto, cancellato o modificato se se ne possiede il permesso in scrittura; puo' essere eseguito se se ne possiede il permesso in esecuzione. I permessi di accesso al file sono 9 caratteri suddivisi in blocchetti di 3. I primi 3 caratteri sono relativi al proprietario del file, i successivi 3 sono relativi al gruppo al quale appartiene il proprietario e gli ultimi 3 sono relativi a tutti gli altri utenti del sistema. Ogni terna puo' contenere i caratteri '-', 'r', 'w' o 'x'. Il carattere '-' disabilita un permesso. Il primo carattere di ciascuna terna puo' assumere i valori '-' o 'r'. Il carattere 'r' indica la possibilita' di leggere il file (r sta per read, cioe' lettura) mentre il carattere '-' al contrario indica che la lettura di tale file non e' possibile. Il secondo carattere di ciascuna terna puo' assumere i valori '-' o 'w'. Il carattere 'w' indica la possibilita' di scrivere il file (w sta per write, cioe' scrittura). Percio' la presenza di una 'w' indica che il file e' scrivibile mentre la presenza del carattere '-' indica che tale file non puo' essere sovrascritto o modificato. Infine il terzo carattere di ciascuna terna puo' assumere i valori '-' o 'x'. Il carattere 'x' indica la possibilita' di eseguire il file (x sta per eXecute, cioe' esecuzione). Al solito il carattere '-' indica che tale file non e' eseguibile mentre il carattere 'x' lo rende eseguibile. Se osserviamo la prima terna allora stiamo considerando i permessi di accesso al file posseduti dal proprietario, se osserviamo la seconda terna stiamo considerando i permessi posseduti dal gruppo a cui appartiene il proprietario ed infine, se osserviamo la terza terna, stiamo considerando i permessi di accesso posseduti da tutti gli altri utenti su tale file. Nell'esempio precedente il file 'file4' e' di proprieta' dell'utente mau. L'utente mau puo' leggere tale file (carattere 'r' presente), puo' sovrascriverlo o modificarlo (carattere 'w' presente) ma non puo' eseguirlo (carattere 'x' non presente). Il gruppo utenti (a cui appartiene mau) puo' invece leggere tale file ed eseguirlo, ma non puo' modificarlo. Tutti gli altri utenti del sistema non possono ne' vedere ne' scrivere ne' eseguire il file 'file4'. Un file che puo' essere visto, modificato ed eseguito da qualsiasi utente del sistema avra' tutti i permessi di accesso abilitati, percio' le tre terne saranno valorizzate cosi': rwxrwxrwx. Cio' significa infatti che il proprietario del file lo potra' leggere scrivere ed eseguire, ma anche il gruppo a cui appartiene il proprietario potra' leggere, scrivere ed eseguire tale file; stessa cosa per tutti gli altri utenti, che potranno leggere, scrivere ed eseguire il file. Inizialmente un file contenuto all'interno di una directory eredita i permessi che possiede la directory (che come ricordiamo e' essa stessa un file) ma e' possibile cambiare tali permessi mediante il comando chmod. L'utente root o supervisore e' il proprietario di tutti i file del sistema, pertanto puo' leggere, scrivere ed eseguire qualsiasi file. Inoltre l'utente root puo' modificare i permessi dei file in modo da allargare o restringere l'accesso ad alcuni file agli altri utenti del sistema. Generalmente l'utente medio possiedera' una propria directory (directory home) all'interno della quale potra' creare, modificare eseguire e leggere qualsiasi file. L'accesso a file contenuti all'interno di altre directory esterne alla directory home sara' pertanto inibito. Cio' avviene per motivi di sicurezza, in quanto in caso contrario un utente medio potrebbe accidentalmente distruggere alcuni file di sistema vitali. Al contrario l'utente root in quanto amministratore del sistema deve poter accedere a qualsiasi file. Per evitare di cancellare file importanti accidentalmente, e' utile collegarsi al sistema in qualita' di utente root per il tempo minimo indispensabile a svolgere operazioni di amministrazione mentre per le operazioni di routine quotidiane quindi e' consigliabile collegarsi come semplice utente. Ovviamente un utente che non possiede il permesso di lettura su un file, non potra' nemmeno cambiarne i permessi di accesso. Per modificare i permessi di accesso di un file occorre usare il comando chmod. Tale comando accetta due argomenti: un elenco di variazioni di permessi ed un elenco di file sui quali agire. Per abilitare un permesso occorre usare il simbolo '+' affianco al tipo di permesso che si desidera modificare. Ad esempio la stringa '+w' abilita il permesso di scrittura mentre la stringa '+x' abilita il permesso di esecuzione. Al contrario per disabilitare un permesso occorre usare il simbolo '-'. E' possibile usare una qualsiasi combinazione di questi simboli. Ad esempio, il comando: chmod +w-x dati abilita la scrittura e disabilita l'esecuzione del file 'dati' per tutti gli utenti. Per specificare la tipologia di utenti ai quali abilitare o disabilitare dei permessi esistono 3 simboli: 'u', 'g' ed 'o'. Il simbolo 'u' sta per user ed indica il proprietario del file, il simbolo 'g' sta per group ed indica il gruppo di utenti del quale fa parte il proprietario ed infine 'o' sta per other, cioe' tutti gli altri utenti. Il simbolo che specifica la categoria di utenti per i quali si desidera modificarne i permessi va specificato prima degli altri simboli. Ad esempio, il comando: chmod g+w-x dati abilita il gruppo di utenti del quale fa parte il proprietario del file per la scrittura e li disabilita per l'esecuzione. Per abilitare piu' permessi non occorre ripetere il simbolo '+' piu' volte, cosi' come non e' necessario per il simbolo '-'. Ad esempio per abilitare sia la lettura che la lettura si puo' scrivere +rw mentre per abilitare in lettura e disabilitare la scrittura e l'esecuzione occorrera' scrivere +r-wx e cosi' via. Se non viene specificata alcuna categoria di utenti si intende modificare i permessi per tutte le categorie. Per specificare tutte le categorie si puo' usare anche il simbolo 'a' , tale simbolo infatta sta per all, cioe tutti. E' da notare che tra i vari simboli non esiste alcuno spazio, occorre infatti scrivere tutti i simboli uno affianco all'altro senza interporre spazi: in caso contrario il sistema rispondera' con un messaggio di errore. Questo modo di specificare i permessi di accesso sui file utilizza dei simboli, percio' viene definito simbolico ma non e' l'unico modo possibile: esiste infatti un altro modo definito assoluto. Il modo assoluto utilizza le cosidette maschere binarie. E' possibile specificare i permessi per ogni categoria di utenti singolarmente usando il metodo simbolico ma e' anche possibile specificare tutti i permessi di tutte le categorie di utenti contemporaneamente usando le maschere binarie. Il vantaggio delle maschere binarie e' la possibilita' di cambiare tutti i permessi usando un solo comando, lo svantaggio e' minore semplicita' d'uso. Infatti il metodo simbolico fa uso di simboli che sono abbastanza facili da ricordare (r per lettura, w per scrittura e via dicendo). Il metodo assoluto al contrario fa uso di maschere binarie. In una maschera binaria le tre categorie di utenti ossia le tre terne di simboli diventano 3 cifre in formato ottale, nel senso che ciascuna categoria e' rappresentata da un numero in base 8. Ogni numero ottale e' equivalente ad un numero di 3 cifre binarie:
0 - 000 Attenzione a non fare confusione: 1, 2, 3, 4 etc. non sono cifre decimali ma sono cifre ottali! Cio' signfica che nel sistema ottale non esiste il simbolo '8' ne' tantomeno il simbolo '9' caratteristici del sistema decimale. Infatti 8 nel sistema otale si scrive cosi': 10. Nel sistema binario, cioe' in base 2, non esistono 10 simboli come ne sistema decimale, ne' 8 simboli come nel sistema ottale, ma 2 simboli: 0 ed 1. Ad ogni modo come si puo' vedere dalla tabella esposta sopra, la cifra ottale 0 corrisponde alla cifra binaria 000 mentre la cifra ottale 4 ad esempio, corrisponde alla cifra binaria 100. Percio' considerando ciascuno di questi 3 numeri binari come uno switch, cioe' un interruttore che puo' essere acceso o spento, possiamo abilitare o disabilitare un permesso. Il primo numero corrisponde al permesso di lettura, il secondo al permesso di scrittura ed il terzo al permesso di esecuzione. Il numero zero corrisponde all'interruttore spento, cioe' ad un permesso disabilitato, mentre il numero 1 corrisponde all'interruttore acceso, cioe' ad un permesso abilitato. Capito cio', e' facile osservare come la cifra ottale 5 ad esempio, corrisponda alla cifra binaria 101, cioe' primo interruttore acceso, secondo interruttore spento e terzo interruttore acceso che tradotto in altri termini significa lettura abilitata, scrittura disabilitata ed esecuzione abilitata. Cosi' 000 disabilita tutti i permessi mentre 111 al contrario li abilita tutti. Tradotto in base ottale significa che 0 disabilita tutti i permessi mentre 7 li abilita tutti, 4 abilita solo la lettura, 1 solo l'esecuzione e cosi' via. Ecco la corrispondenza con i simboli visti precedentemente:
0 - 000 - --- A questo punto risulta evidente che per rappresentare le 3 terne corrispondenti alle tre categorie di utenti sono sufficienti 3 cifre ottali. La prima cifra ottale infatti e' relativa al proprietario del file, la seconda al gruppo a cui appartiene e la terza a tutti gli altri utenti del sistema. Usando questo sistema con 000 disabilitiamo tutti i permessi a tutti gli utenti proprietario compreso (non consigliabile) ;o) mentre con 777 abilitiamo tutti i permessi a tutti gli utenti (altamente non consigliabile) ;o) Con tale sistema e' possibile ad esempio fornire tutti i permessi al proprietario del file e permettere unicamente la lettura del file stesso a tutti gli altri utenti specificando unicamente la cifra 744. Calcolare di volta in volta le cifre ottali a partire dalla maschera binaria non e' molto comodo ma esiste in realta' un comodo trucchetto per ovviare a questo problema. Consideriamo la seguente tabella:
4 - 100 - r-- la cifra ottale 4 abilita il permesso in lettura, la cifra 2 il permesso in scrittura e la cifra 1 il permesso in esecuzione. Bene, a questo punto per ricavare tutte le combinazioni di permessi possibili e' sufficiente sommare queste 3 cifre ottali. Ad esempio, per abilitare lettura e scrittura occorre sommare 4 e 2 per ottenere 6 (che come si puo' osservare nella tabella precedente corrisponde proprio alla stringa 'rw-' cioe' lettura e scrittura abilitate ed esecuzione disabilitata). Per abilitare lettura ed esecuzione e' sufficiente sommare 4 ad 1 per ottenere 5 (cioe' 'r-x'). Alla luce di tutto cio', per abilitare tutti i permessi al proprietario del file 'dati' e permettere a tutti gli altri utenti solo la lettura e l'esecuzione occorrera' usare il comando chmod in questo modo: chmod 755 dati I permessi di accesso sulle directoryCome gia' detto le directory sono esse stesse dei file anche se un po' speciali. Conseguentemente e' evidente che e' possibile specificare i permessi di accesso anche per le directory. Esistono comunque delle sottili differenze. Il permesso di lettura su una directory infatti permette di elencare tutti i file contenuti all'interno, permette cioe' di leggerne il contenuto. Il permesso di scrittura permette di aggiungere nuovi file nella directory, permette cioe' di scrivere al suo interno. Il permesso di esecuzione infine, permette di accedere all'interno della directory. La conseguenza logica di cio' e' che se un file leggibile, scrivibile ed eseguibile viene posto all'interno di una directory che non e' accessibile (perche' ha il permesso di esecuzione disabilitato) il file stesso diventa inaccessibile! Per accedere ad un file pertanto, non e' sufficiente abilitarne i permessi ma occorre che la directory che lo contiene, cosi' come la directory genitrice e tutte le altre directory padre siano abilitate in esecuzione. Non occorre che tali directory siano abilitate anche in lettura. In questo modo si potra' accedere al file accedendo a tutte le directory del percorso senza pero' poter visionare il contenuto di tutte le directory. Ad esempio il file : /home/mau/guida.html puo' essere accessibile a tutti gli utenti del sistema se guida.html ha il permesso di lettura abilitato, se la directory mau ha il permesso di esecuzione abilitato per tutti gli utenti e se la directory home ha il permesso di esecuzione abilitato per tutti gli utenti. L'utente Francesca pertanto potra' leggere il file guida.html tranquillamente, ma non potra' elencare il contenuto della directory mau ne' tantomeno quello della directory home. Cambiare il proprietario od il gruppo di un fileAnche se un utente puo' accedere ad un file, solo il prorpietario puo' cambiarne i permessi. Se si vuole quindi cedere il controllo di un file ad un altro utente, occorre cambiarne il proprietario. Per cambiare il proprietario di un file occorre usare il comando chown. Chown sta per 'change owner', cioe' cambia proprietario. Il comando chown accetta due argomenti il primo che e' il nome del nuovo proprietario e il secondo che e' il nome di un file o un elenco di file. Ad esempio per cambiare il proprietario di guida.htm occorre scrivere: chown francesca guida.html Se visualizziamo il file guida.html prima del comando chown infatti, otteniamo:
ls -l guida.html ma una volta eseguito il comando chown avremo:
ls -l guida.html Come si puo' vedere il proprietario di guida.html da mau e' diventato francesca. Allo stesso modo e' possibile cambiare il gruppo su un file utilizzando questa volta il comando chgrp. Il comando chgrp sta per 'change group' cioe' cambia gruppo ed accetta 2 argomenti: il nuovo gruppo ed il file (o l'elenco di file) che deve essere modificato. I dispositivi ed il comando mountGeneralmente ogni file in un sistema Linux si trova all'interno di una directory. Il sistema di file di Linux (filesystem) e' percio' costituito da un insieme di directory e sottodirectory una all'interno dell'altra e formano logicamente una struttura gerarchica ad albero. Esiste infatti una directory radice (o root) cioe' la directory '/' dalla quale si ramificano tutte le altre sottodirectory. I file contenuti nel filesystem di Linux possono risiedere fisicamente tutti all'interno dello stesso dispositivo di memorizzazione - tipicamente il disco fisso - o su piu' supporti fisici distinti come ad esempio CD-Rom, floppy disk, nastri, unita' di memorizzazione ottica, unita' disco supplementari e via dicendo. Ciascuno di questi dispositivi contiene al suo interno un proprio filesystem (o anche piu' di uno) cioe' una propria struttura ad albero. Il filesystem contenuto in un dispositivo puo' essere lo stesso di quello contenuto nel disco dove risiede il sistema oppure puo' essere diverso. Per poter accedere al filesystem del dispositivo occorre collegare fisicamente il dispositivo al sistema ma occorre anche collegare il suo filesystem al filesystem generale dove risiede il sistema. Si puo' pensare al filesystem del dispositivo aggiuntivo come ad una sorta di sottoalbero che deve essere collegato all'albero generale. Tale operazione di collegamento prende il nome di mount. L'operazione di mount cioe' collega un dispositivo al sistema ed e' un'operazione eseguibile unicamente dall'utente root. Un utente generico pertanto non puo' eseguire tale operazione. Cio' e' logico in quanto l'operazione di manutenzione ed amministrazione del sistema e' compito dell'utente root (supervisore) che e' appunto l'amministratore del sistema. Con il comando mount occorre specificare il tipo di dispositivo da collegare al sistema ed il punto di mount, cioe' la directory che fungera' da radice per il sottoalbero contenuto nel dispositivo. Con il comando di mount si puo' collegare anche un filesystem diverso da quello di Linux contenuto magari nello stesso disco fisico ma in una partizione diversa. Questo e' tipico dei sistemi multiboot dove nello stesso disco risiedono due o piu' sistemi operativi (tipicamente Linux e Windows). A differenza dei sistemi tipo Windows occorre percio' ricordare che anche per accedere ai dati contenuti in un normale floppy disk o di un CD-Rom occorre prima effettuare l'operazione di mount. Inoltre se occorre leggere piu' floppy disk o piu' CD-Rom, occorre montare e 'smontare' ogni volta ciascun dispositivo. L'operazione inversa al mount e' l'operazione di umount. In realta' cio' non e' sempre vero in quanto per ovvi motivi di comodita' e' stato ideato un tipo particolare di mount, il supermount. Si tratta in realta' di un programma che rimane sempre attivo nel sistema anche se in stato letargico. E' un programma che sonnecchia ma che si sveglia immediatamente non appena viene inserito un nuovo dispositivo nel sistema. E' cio' che viene definito demon, cioe' demone. Non appena viene inserito un CD-Rom ad esempio, tale programma si attiva ed effettua il mount del dispositivo. Una volta estratto il CD-Rom il demone effettua l'operazione inversa e cioe' l' umount. Occorre precisare che un sistema Linux puo' essere configurato in modo da effettuare le operazioni di mount che si rendono necessarie in fase di bootstrap, cioe' in fase di avvio. Come gia' detto con il comando mount occorre specificare il tipo di dispositivo che si vuole collegare al sistema. I vari dispositivi utilizzabili in un sistema Linux sono contenuti all'interno della directory di sistema /dev (dove dev sta per devices, cioe' dispositivi appunto). Ciascun dispositivo ha un nome ben preciso sotto Linux, ad esempio i floppy disk si chiamano fd (floppy disk appunto) gli hard disk hd (hard disk) i CD-Rom hd (gia' i CD-Rom sono visti come gli hard disk) e via dicendo. Se sono presenti piu' dispositivi dello stesso tipo vengono enumerati usando una cifra finale. Cioe' non e' vero per gli hard disk ed i CD-Rom che vengono enumerati usando una lettera finale. Ad esempio il primo disco del sistema sara' hda mentre un disco supplementare sara' hdb. Se il sistema contiene 2 dischi ed un CD-Rom allora il CD-Rom sara hdc. I dischi fissi possono essere divisi in partizioni. Ogni partizione e' contraddistinta da un numero pertanto se il primo disco del sistema contiene diciamo 3 partizioni, tali partizioni si chiameranno hda1, hda2 e hda3. Se oltre al primo disco viene collegato un CD-Rom, tale dispositivo sara' hdb. Supponendo di voler collegare un floppy disk al sistema, occorrera' usare il seguente comando: mount /dev/fd0 /mnt/floppy con tale comando viene collegato il filesystem contenuto nel floppy al filesystem generale del sistema a partire dalla directory /mnt/floppy. In realta' si poteva collegare tale dispositivo alla directory /home/miodisco o alla directory /pippo, ma per convenzione le operazioni di mount vengono effettuate collegando i vari dispositivi all'interno della directory /mnt (mnt sta per mount appunto). Pertanto la directory /mnt solitamente conterra' al suo interno delle sottodirectory come floppy, cdrom etc. Se il dispositivo che si vuole collegare al sistema contiene un filesystem diverso da quello utilizzato da Linux occorre allora specificare il tipo di filesystem usato. Se ad esempio il floppy disk che intendiamo collegare contiene dei dati scritti in ambiente DOS/Windows occorre specificare 'vfat' come tipo di filesystem. Per specificare il tipo di filesystem occorre usare l'opzione -t (type cioe' tipo) del comando mount: mount -t vfat /dev/fd0 /mnt/floppy All'interno di un sistema Linux sono generalmente presenti piu' partizioni e magari esiste una partizione che contiene un sistema Windows. Tipicamente in un sistema Linux esistono almeno due partizioni, la partizione di swap e la partizione di root. Per collegare tutte queste partizioni al sistema si puo' ovviamente usare il comando mount, ma poiche' si tratta di una operazione ripetitiva che va eseguita ad ogni avvio del sistema, si puo' in realta' effettuare il mount automaticamente configurando un apposito file di sistema che si chiama fstab (file system table) presente all'interno della directory di sistema /etc. Ogni partizione o dispositivo presente nel file fstab viene collegato con il relativo comando di mount automaticamente all'avvio del sistema e scollegato con il corrispondente comando di umount in fase di chiusura del sistema. Come gia' visto precedentemente per creare una partizione all'interno di un disco occorre usare il comando fdisk. Una volta creata la partizione occorre creare il filesystem con il comando mkfs (MaKe FileSystem, cioe' crea il filesystem). In fase di avvio del sistema viene eseguito il comando mount -a presente nel file /etc/rc.d/rc.sysinit. In questo file sono contenuti tutti i comandi che vengono eseguiti in fase di avvio del sistema. Il comando mount -a viene a conoscenza dei dispositivi da collegare leggendoli dal file fstab. I comandi da eseguire in fase di inizializzazione del sistema non sono sempre presenti nel file /etc/rc.d/rc.sysinit in quanto il nome di tale file varia da distribuzione a distribuzione. Se infatti parliamo di distribuzioni Red Hat allora il file e' /etc/rc.d/rc.sysinit appunto, ma se parliamo ad esempio di distribuzioni Slackware il file si chiama /etc/rc.d/rc.local. Il file fstab contiene una riga per ogni dispositivo da collegare in fase di avvio del sistema. Ogni riga e' composta da 6 colonne. La prima colonna indica il device, cioe' il dispositivo da collegare e puo' essere contenere valori come /dev/hda3, /dec/fd0 o /dev/hdc. La seconda colonna indica il punto di mount (o mountpoint) cioe' la directory che fungera' da radice per il dispositivo e puo' contenere valori come /mnt/floppy /mnd/cdrom /mnt/windows e cosi' via. La terza colonna contiene il tipo di dispositivo (filesystemtype) e puo' contenere valori come ext2, iso9660, swap, vfat e via dicendo. La quarta colonna specifica alcune possibili opzioni (options) e puo' contenere valori come defaults, ro, noauto e via dicendo. La quinta colonna contiene un valore usato dal comando dump ed infine la sesta colonna contiene un valore usato dal comando fsck per sapere se il dispositivo deve essere verificato o meno ed in quale ordine (il comando fsck infatti sta per FileSystem CheK, cioe' controllo del filesystem e viene usato per verificare la presenza di eventuali errori nel file system). Per saperne di piu' sul file fstab consultare la documentazione Linux (si parlera' di documentazione Linux nell'apposito capitolo in seguito). L'archiviazione dei file: i comandi tar e gzipIl comando tar e' stato creato originariamente per archiviare file e directory su nastro (tar infatti sta per Tape ARchive cioe' archivio su nastro) ma in realta' con tale comando e possibile creare degli archivi su qualsiasi dispositivo. Ecco perche' ancora oggi e' molto usato anche su dispositivi diversi dai nastri. Con il comando tar e' possibile creare degli archivi che contengono file ma anche intere directory. E' possibile modificare un archivio creato con il comando tar aggiungendo nuovi file od eliminandone alcuni gia' presenti. Il comando tar percio' e' molto utile per effettuare dei backup. Un archivio creato con il comando tar ha solitamente come estensione '.tar' ma in realta' si tratta di una convenzione che non e' affatto obbligatoria. La sintassi del comando tar e': tar opzioni nomearchivio.tar file-e-o-directory. Le opzioni specificate con il comando tar non devono essere precedute da un trattino al contrario di tutti i comandi Linux. Ad esempio il comando:
tar cf mioarchivio.tar pippodir
crea un archivio chiamato mioarchivio.tar aggiungendo all'interno tutti i file presenti sotto la directory pippodir. Per estrarre
tutti i file e le directory contenute nell'archivio mioarchivio.tar occorre usare lo stesso comando tar ma con le opzioni
di estrazione:
tar xf mioarchivio.tar
Il comando tar non esegue alcuna compressione sui file aggiunti nell'archivio, tuttavia e' possibile creare un archivio
contenente file e directory e comprimerlo in modo da occupare meno spazio. Per far cio' occorre usare l'opzione z.
L'opzione z chiama il comando gzip che effettua la compressione dei file:
tar cfz mioarchivio.tar pippodir
Il file cosi' creato verra' chiamato mioarchivio.tar.gz. Saranno cioe' presenti 2 estensioni: .tar e .gz. Un file con
estensione .gz e' un file compresso e lo si puo' decomprimere usando il comando gzip. Per estrarre i file e le directory
contenute nel file mioarchivio.tar.gz occorre prima decomprimere l'archivio con il comando gzip e successivamente estrarre
i file dall'archivio con il comando tar. Per decomprimere un file compresso si puo' usare il comando gzip con l'opzione -d
oppure si puo' usare il comando gunzip. Nell'esempio precedente, per ripristinare i file originari si dovranno eseguire
i seguenti comandi:
gzip -d mioarchivio.tar.gz (oppure gunzip mioarchivio.tar.gz) e successivamente:
Parlando dei comandi mount ed umount abbiamo visto che le unita' di memorizzazione dei dati vengono definite dispositivi
(o devices). Oltre a tali unita' pero', esistono molti altri dispositivi come i terminali, i modem e le stampanti.
All'interno della directory /dev (devices appunto) sono presenti i vari dispositivi utilizzabili da Linux. Si tratta di
file speciali di sistema chiamati 'file di device'. Il file di device e' un' interfaccia tra Linux ed hardware. Come
gia' visto nel capitolo dedicato all'hardware, ogni dispositivo hardware 'dialoga' con il sistema operativo attraverso
uno speciale programma chiamato driver. Il driver e' un programma molto specializzato scritto generalmente dalle stesse
societa' produttrici di hardware. In Linux il sistema operativo non dialoga direttamente con i vari driver di ciascun
dispositivo hardware ne' tantomeno con l'hardware stesso, ma utilizza i file speciali contenuti nella directory /dev.
Ad esempio, per scrivere su un floppy disk presente nel drive A: Linux utilizza il file di device /dev/fd0.
In questo file di device un numero primario (o Major number) indica il tipo di dispositivo (e di conseguenza il driver da chiamare) mentre il numero secondario (minor number) indica univocamente una unita' fisica del sistema del tipo descritto
dal numero primario (il numero secondario viene passato come parametro al driver). I file di device possono essere di 2 tipi:
a carattere o a blocchi. I device a carattere vengono letti o scritti sequenzialmene un carattere per volta (come ad
esempio le porte seriali) mentre i device a blocchi vengono letti a blocchi di 1024 caratteri per volta (ad esempio
gli hard disk).
Ecco alcuni device presenti nella directory /dev:
fd0 Primo lettore di dischetti
Ecco un esempio di device:
$ ls -l /dev/hda
dove 3 e' il numero primario e 0 e' il numero secondario.
Il nome di un file rappresenta un riferimento ad un punto all'interno del disco dove sono memorizzati i dati
contenuti nel file stesso. In realta' sarebbe piu' corretto dire che ad ogni nome di file viene associato l'i-node
del file stesso. Cioe', per ogni file esiste una coppia 'nome del file'/i-node.
Capiremo questa affermazione in seguito parlando degli i-node, per ora e' possibile comprendere il concetto
pensando agli handle: chi conosce qualche linguaggio di programmazione orientato agli oggetti sa benissimo di cosa
si sta parlando. Handle significa 'maniglia', infatti un handle e' una sorta di maniglia, cioe' uno strumento per
maneggiare degli oggetti. Non e' ancora chiaro? Ecco l'esempio per la massaia: la padella! Supponiamo di possedere
una padella senza manico...supponiamo anche di voler preparare una gustosa frittata alle verdure (personalmente
adoro i peperoni) ;o) Ok, mescoliamo gli ingredienti, mettiamo la padella sulla macchina del gas, accendiamo il fuoco
ed aspettiamo. Ecco ora e' pronta la frittata, occorre versarla nei piatti...ma...accidenti, la padella non ha il
manico! Chi si azzarderebbe a toccarla in questo momento? Hmmm...senza manico, occorrono come minimo delle presine
o dei guanti da forno...gia' gli handle! ;o) Ecco, per 'afferrare' un file che si trova su un disco, un CD-Rom,
un floppy disk o chissa' dove, occorre un manico, una presina, un guanto da forno o meglio un handle: il suo nome appunto.
Il nome di un file e' il suo handle, cioe' la maniglia con la quale maneggiare il file. Nei mondi *nix (*nix sta per
Unix, Linux, Aix, Minix et similia) esiste il concetto di link. Il collegamento tra il nome del file e l'indirizzo fisico
dove si trova il file viene definito 'link' (che significa appunto collegamento). Cio' che abbiamo definito come handle,
nei mondi *nix viene chiamato link. Potremmo percio' definire un link ad un file come il suo nome. Usando il comando
ls:
ls -l pippo
possiamo notare un numero che precede il nome del proprietaro del file, che in questo caso e' mau.
Il numero precedente al nome del proprietario del file (1) e' il numero di link che tale file possiede.
In questo caso esiste un solo link: il nome del file stesso (pippo). Questa e' la situazione normale di un qualsiasi file.
Linux pero' mette a disposizione un comando che permette di creare ulteriori link allo stesso file. Creare un ulteriore link
percio' significa creare un ulteriore nome per referenziare il file o, se si preferisce, un ulteriore handle (o manico,
maniglia, presina, guanto da forno) ;o). Il comando che permette cio' e' il comando ln (LiNk, cioe' collegamento):
ls
Come si puo' vedere pippo e pippo2 hanno 2 come numero di link il che significa che pippo2 e' semplicemente un altro nome
che referenzia sempre lo stesso file. Attenzione: pippo2 non e' la copia di pippo ma si tratta proprio dello stesso file.
Se si modifica pippo e si visualizza il contenuto di pippo2 si notera' che pippo2 e' identico a pippo: infatti sono lo
stesso file. Se pippo2 fosse una copia di pippo, modificando pippo, pippo2 rimarrebbe invariato. Poiche' pippo2
e' un secondo nome dello stesso file, cancellando pippo sara' sempre possibile far riferimento al file usando pippo2.
Per tornare all'esempio della padella, quando si crea un link ad un file si sta aggiungendo un nuovo manico alla padella:
se se ne rompe uno, e' sempre possibile afferrare la padella usando l'altro manico. La padella diventa inusabile solo
quando non possiede piu' alcun manico. Tornando ai file, cio' significa che: un file viene cancellato effettivamente solo
quando vengono eliminati tutti i suoi link:
ls -l
Questo appena visto e' un 'link fisico'(hard link) e puo' ad esempio essere utile per far riferimento ad un file da una directory
diversa da quella all'interno della quale si trova il file. Ad esempio, il file pippo potrebbe risiedere nella directory /home/mau
mentre il link pippo2 potrebbe risiedere nella directory /home/francesca. Si potra' accedere al file pippo dalla directory /home/mau
oppure dalla directory /home/francesca usando il riferimento pippo2:
pwd (visualizzo la directory corrente: /home/mau)
pippo2 non e' la copia di pippo: modificando pippo nella directory /home/mau e visualizzando pippo2 nella directory
/home/francesca, noteremo che pippo2 conterra' le modifiche fatte a pippo: infatti sono due nomi che referenziano
lo stesso file. Come e' possibile scoprire se pippo e pippo2 sono lo stesso file o file diversi? Visualizzando il
numero di i-node di entrambi i file usando il comando ls e l'opzione -i:
ls -i pippo pippo2
ls -i visualizza il numero di i-node (-i sta per i-node appunto). In questo esempio vediamo che pippo e pippo2 hanno
lo stesso i-node: possiamo essere certi che si tratta dello stesso file, in quanto per ogni file esiste un solo i-node
e ad ogni i-node e' associato un solo file. Ma se e' possibile creare un secondo nome (od un terzo, un quarto e cosi' via)
per un file comune, non e' possibile dare piu' nomi ad una directory. Per essere piu' corretti in verita' occorre dire
che non e' possibile creare un link fisico ad una directory, ma e' possibile crearne uno simbolico. Un link simbolico
non e' un nome aggiuntivo ma e' un file speciale che contiene al suo interno il puntatore al file, o meglio, il
percorso da fare per raggiungere il file. Per creare un link simbolico occorre usare il comando ln con l'opzione -s:
ln -s pippo pippo2
questo comando crea un link simbolico, cioe' un file speciale che contiene il percorso del file originario. Per evidenziare
cio' si puo' usare il comando ls con le opzioni i ed l:
ls -il pippo pippo2
Hmmm, come si puo' vedere il comando ln con l'opzione -s crea un nuovo file mentre il comando ln senza opzioni
crea un secondo nome ma non un secondo file. Cio' lo si evince esaminando il numero di i-node: il file pippo ha i-node
15436 mentre il file pippo2 ha i-node 15437. Si tratta a tutti gli effetti di 2 file diversi. Inoltre possiamo notare
che le dimensioni dei due file sono diverse: 553 byte il file pippo e 5 byte il file pippo2. Una differenza ulteriore
e' il carattere che identifica il tipo di file: nel file pippo e' presente un trattino (file comune) nel file pippo2
e' presente la lettera l (link). Infine, alla fine della riga relativa al file pippo2 e' presente una informazione
ulteriore: una freccia che indica il collegamento tra pippo2 e pippo. La conseguenza piu' immediata di tutto cio'
e' che cancellando pippo, pippo2 puntera' ad un file inesistente.
ls -li
cercando di visualizzare il file originario usando il link simbolico pippo2 otterremo un messaggio di errore dalla shell:
no such file or directory. Il link ora punta ad un file che non esiste piu' in quanto e' stato cancellato.
A parte questa differenza, in quali casi e' utile usare un link simbolico? Ad esempio quando si vuole creare un link
ad una directory oppure quando si vuole creare un link ad un file o ad una directory che si trova all'interno di un filesystem diverso.
Con un link simbolico infatti e' possibile far riferimento ad un file che si trova in un dispositivo diverso o addirittura in un filesystem diverso.
A questo punto e' il caso di esaminare in maggiore dettaglio questo fantomatico i-node. A dire il vero non e' indispensabile conoscere il filesystem ext2 in dettaglio ma le informazioni che seguono sono utili a mio avviso per capire a fondo il significato di link fisico e di link simbolico: il lettore non troppo curioso puo' decidere di saltare questo paragrafo
e passare al capitolo successivo. Ma torniamo all'i-node. L'i-node e' una struttura presente nel filesystem ext2 ed in altri filesystem *nix. Esistono vari filesystem come ad esempio ext2 (extended 2), fat (file allocation table), nfs (network file system), hfs (hierarchical file system) e molti altri. Linux (a differenza di altri sistemi operativi) supporta un gran numero di filesystem diversi. Ma cosa e' un filesystem? Un filesystem e' una architettura che comprende i metodi e le strutture dati usate da un sistema operativo per memorizzare i file su un supporto fisico. Ogni sistema operativo possiede un determinato filesystem. Ad esempio i sistemi macintosh usano hfs, mentre i sistemi dos/windows usano fat. Linux puo' usare vari filesystem come ad esempio ext, ext2, ext3 o reiserfs, ma supporta anche i filesystem di sistemi operativi diversi. Il filesystem piu' diffuso in ambito Linux e' attualmente ext2, vediamolo in dettaglio. Il filesystem ext2 e' suddiviso in piu' parti chiamate cylinder group. Ogni cylinder group e' un pezzo di disco a se' stante questo affinche' in caso di problemi con un cylinder group, tutti gli altri possano essere ancora utilizzabili. L'utilita' dei cylinder group e' anche quella di poter ridurre i tempi di accesso ai file, memorizzando i file e le directory che li contengono all'interno dello stesso cylinder group. All'interno di ogni cylinder group sono presenti varie tabelle e strutture. Un struttura abbastanza importante si chiama super_block e contiene varie informazioni come le caratteristiche e le dimensioni del filesystem stesso nonche' alcune variabili di stato (blocchi liberi, numero di mount effettuati etc). Ecco un super_block in dettaglio:
/*
Tra le varie informazioni sono presenti un contatore di i-node, un contatore di blocchi e la dimensione di ogni blocco.
Data l'importanza di questa struttura, essa viene duplicata all'interno di ogni cylinder group, in modo da poter
disporre di copie di riserva in caso di errori e di problemi. All'interno di ogni cylinder group sono presenti inoltre
un group descriptor, una block bitmap, una i-node bitmap ed una i-node table. Il group descriptor contiene informazioni
di controllo relative all'intero gruppo:
struct ext2_group_desc {
Un elemento importante all'interno del group descriptor e' il puntatore al blocco che contiene la tabella degli i-node.
La block bitmap e' una mappa di bit dove ogni bit indica quali blocchi sono allocati. La i-node bitmap indica gli i-node allocati e la i-node table contiene gli i-node che appartengono a quel cylinder group. Su Linux i dati vengono memorizzati all'interno di blocchi di 1024 byte (ma possono anche diventare 2048 o 4096). Si tratta di blocchi logici in quanto solitamente i blocchi fisici di un disco sono lunghi 512 byte (un blocco logico contiene 2 o piu' blocchi fisici).Il blocco
e' l'area minima allocabile sul disco. In altre parole se un file e' lungo 10 byte verra' allocato un blocco logico mentre se e' lungo ad esempio 2000 byte verranno allocati 2 blocchi. Abbiamo detto che la i-node table contiene l'elenco degli i-node all'interno del cylinder group, ma cosa e' un i-node? Si potrebbe definire l'i-node come la carta di identita' di ogni file. Infatti l'inode e' una struttura che contiene gli attributi e le caratteristiche del file a cui e' legato (i-node sta per information node, cioe' nodo di informazione). Esiste un i-node per ogni file. Ogni i-node e' identificato da un numero univoco. All'interno di questa struttura troviamo le seguenti informazioni: i permessi di accesso al file, l'identificativo del proprietario del file, le dimensioni in byte, la data dell'ultimo accesso al file, la data di creazione, la data dell'ultima modifica, la data di cancellazione, l'identificativo del gruppo, un contantore dei link ed un contatore dei blocchi. Ogni i-node inoltre, possiede una tabella di puntatori ai blocchi che contengono i dati del file. Ecco una parte della struttura dell'i-node:
struct ext2_inode {
Per semplicita' non esaminiamo il resto della struttura che contiene tra l'altro una tabella di 15 puntatori a blocchi:
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
Il primo elemento della struttura (i_mode) contiene tra l'altro il tipo di file (comune, directory, speciale etc) ed i permessi di accesso al file (read, write, execute). Un altro elemento importante e' la tabella di puntatori ai bloccchi (i_block). Come visto in precedenza un file puo' essere spezzato in piu' blocchi logici da 1024 byte ciascuno. La tabella di puntatori ai blocchi del file e' costituita da 15 elementi. Ogni elemento contiene un puntatore ad un blocco. Poiche' 1024 x 15 = 15360, si potrebbe pensare che la lunghezza massima di un file debba essere di 15360 byte, ma non e' cosi'. Infatti i primi 12 elementi della tabella contengono in effetti un puntatore ad un blocco di dati ciascuno chiamato direct block, ma le cose cambiano dal tredicesimo elemento in poi. Infatti nell'elemento 13 della tabella dei puntatori ai blocchi contiene un puntatore ad un blocco che non contiene dati ma un'altra tabella di puntatori. Questo blocco si chiama indirect block. All'interno di questa tabella ogni elemento contiene un puntatore ad un blocco di dati.
L'elemento 14 contiene un puntatore ad un blocco di puntatori che a loro volta non puntano a blocchi di dati (a differenza
di quelli puntati dal puntatore dell'elemento 13) ma puntano ad altri blocchi di puntatori. Questi ultimi blocchi di puntatori puntano a blocchi di dati. Il blocco di puntatori puntato dal puntatore dell'elemento 14 si chiama double indirect block. Infine l'elemento 15 della tabella di puntatori ai blocchi contenuto nell'i-node punta ad un blocco di puntatori chiamato triple indirect block. Il blocco triple indirect block punta ad un blocco di puntatori ognuno
dei quali punta ad un altro blocco di puntatori ognuno dei quali punta ad un blocco di dati. Poiche' ogni blocco logico
generalmente e' lungo 1024 byte e poiche' nei sistemi con registri a 32 bit un puntatore ad interi occupa 4 byte (4 byte da 8 bit ciascuno significano 4 x 8 = 32 bit, come ben sa chi programma in linguaggio C) se ne deduce che 1024 / 4 = 256, cioe' ogni blocco di puntatori puo' contenere 256 puntatori a blocchi. Ad ogni modo l'immagine seguente chiarisce l'intero sistema di puntatori a blocchi:
Vediamo infine la struttura delle directory. Una directory e' un file speciale che contiene al suo interno delle informazioni
relative ai file che contiene. Vediamo la struttura di una directory:
#define EXT2_NAME_LEN 255
Ogni directory possiede una tabella all'interno della quale esiste una coppia di elementi che contengono rispettivamente il nome del file (char name[EXT2_NAME_LEN]) e l'i-node associato (__u32 inode;). Ogni all'interno di una directory possiede una coppia di elementi. Esistono tante coppie quanti sono i file contenuti all'interno della directory. Quando viene creato un link fisico ad un file non viene fatto altro che inserire una nuova coppia di elementi:
ls
la directory corrente contiene 3 file: pippo, pluto e topolino. Cio' significa che la tabella di tale directory conterra'
3 coppie di elementi:
pippo 10500 (i-node numero 10500)
se creiamo un link al file pippo con il comando 'ln pippo pippolink' il sistema aggiungera' una quarta coppia all'interno
della tabella:
pippo 10500 (i-node numero 10500)
come possiamo vedere sia a pippo che a pippolink e' associato l'i-node numero 10500. Possiamo pertanto asserire che
ogni volta che si crea un link ad un file il sistema non fa altro che creare una nuova entrata (entry) cioe' una nuova
coppia "nome file"/i-node all'interno della tabella della directory. Il filesystem ext2 puo' avere una dimensione massima
di 4 terabyte, ciascun file puo' avere una dimensione massima di 2 gigabyte ed il nome di ogni file puo' essere lungo
al massimo 255 caratteri.
Il filesystem ext2 a differenza di ext3 e di reiserfs e' un filesystem non journalled. Cosa e' il journalling? Come abbiamo visto all'interno di un filesystem i dati vengono scritti all'interno di blocchi e successivamente vengono aggiornate tutte le relative tabelle e strutture (come gli i-node ad esempio). Quando viene effettuato lo shutdown del sistema, Linux scrive su disco tutti i dati che erano presenti nelle aree di lavoro, successivamente aggiorna le varie strutture e tabelle del filesystem ed infine 'smonta' i dischi e le partizioni. Al successivo avvio il sistema monta nuovamente dischi e partizioni e verifica tutte le strutture del filesystem: se tutto e' in ordine avvia tutti i processi del sistema. Tutto cio' accade in situazioni normali. Il problema si pone in situazioni anomale, ad esempio in caso di improvvisa mancanza di corrente o di crash di sistema. Cosa accade in tali circostanze? Cadendo improvvisamente la tensione o grazie ad un crash, il sistema non e' in grado di memorizzare i dati presenti nelle arre di lavoro (in memoria) e di aggiornare le strutture del filesystem, percio' e' costretto ad effettuare una scansione completa del disco per rilevare eventuali errori o situazioni rimaste in sospeso. Questa operazione e' tristemente nota a tutti gli utilizzatori dei sistemi Windows in quanto a seguito di un crash di sistema al successivo avvio parte il famoso programma scandisk... ;o) Ad ogni modo questa scansione del disco richiede tempo e non elimina il problema della possibile perdita dei dati relativi agli ultimi aggiornamenti che si stavano effettuando prima della chiusura anomala del sistema. Il sistema del journalling offre una soluzione a questi problemi. Con il journalling viene creata una nuova struttura all'interno del filesystem: il journal. Il journal e' una sorta di diario dove viene inserita una nuova entrata prima di effettuare una modifica su disco. Questo sistema permette di tenere traccia delle ultime modifiche effettuate. In caso di crash del sistema o di interruzione di corrente elettrica al successivo riavvio il sistema effettua il controllo del filesystem pero' con una differenza: non viene piu' effettuata una scansione dell'intero disco (operazione che su grossi dischi puo' richiedere parecchi minuti) ma, utilizzando il journal, controlla solamente le parti del filesystem relative alle ultime modifiche (operazione che richiede pochi secondi). Per maggiori informazioni riguardo il filesystem consultare il relativo howto all'indirizzo:
http://www.penguin.cz/~mhi/fs/Filesystems-HOWTO/Filesystems-HOWTO.html
Copyright (c) 2002 M. Silvestri |