[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [translators] [docinfo] [indice analitico] [volume] [parte]
Quelle indicate nel titolo del capitolo sono fasi fondamentali dell'amministrazione dei dati. Nello stesso modo sono anche operazioni molto delicate. La tabella 125.1 elenca i programmi a cui si accenna in questo capitolo.
La copia genera un altro file o un'altra directory, il collegamento genera un riferimento aggiuntivo agli stessi dati di origine: assomiglia alla copia, ma rappresenta solo un modo per fare apparire la stessa cosa in più punti differenti.
Nei sistemi Unix i collegamenti sono molto importanti e vengono usati di frequente. Si distinguono due tipi di questi: collegamenti simbolici (symbolic link) e collegamenti fisici (hard link). Attraverso il collegamento fisico si creano dei riferimenti a dati esistenti in modo non distinguibile da quelli originali; i collegamenti simbolici sono dei file speciali e per questo distinguibili dai file originali.
A fianco del problema della copia di file (o di directory), cioè di entità virtuali per il contenimento dei dati, ci può essere il problema elementare (anche se complicato per l'utente) di trasferire dati attraverso i dispositivi in modo diretto (copia a basso livello).
Si è accennato al fatto che i collegamenti simbolici sono dei file speciali, distinguibili dai file originali. Si creano normalmente utilizzando il programma ln, con l'opzione -s, come nell'esempio seguente:
$
ln -s /bin/sh ./sh
[Invio]
Seguendo l'esempio, se si leggono le caratteristiche del file ./sh
attraverso ls, si può notare l'indicazione esplicita del fatto che si tratta di un riferimento al file /bin/sh
(il quale potrebbe essere un altro collegamento, ma questo adesso non è importante).
$
ls -l sh
[Invio]
lrwxrwxrwx 1 tizio tizio 7 Mar 2 10:16 sh -> /bin/sh |
La lettera che appare all'inizio dei permessi, «l», indica esplicitamente che si tratta di un collegamento simbolico. Alla fine, viene indicato anche a chi punta il collegamento: -> /bin/sh.
Si può osservare inoltre che i permessi di un collegamento simbolico non esistono. Formalmente vengono mostrati come attivi tutti i permessi degli ultimi 9 bit (lettura, scrittura ed esecuzione per tutti gli utenti), perché quelli che contano sono in realtà i permessi del file (o della directory) cui effettivamente punta il collegamento simbolico.
La gestione dei collegamenti fisici è più seria, nel senso che deve essere riservata a situazioni di particolare necessità. Attraverso il collegamento fisico si creano dei riferimenti a dati esistenti in modo non distinguibile da quelli originali; in pratica, due o più voci nella stessa directory, o in directory differenti, possono puntare allo stesso file.
Quando si cancella un file, si elimina il riferimento al suo inode dalla directory che lo contiene formalmente. Quando un inode non ha più riferimenti, viene considerato libero e può essere riutilizzato per un altro file. In altre parole, se si utilizzano i collegamenti fisici, un file viene cancellato effettivamente quando sono stati eliminati tutti i riferimenti a questo.
Per comprendere in pratica cosa accade, si può provare con gli esempi seguenti.
$
touch mio_file
[Invio]
$
ls -l mio_file
[Invio]
-rw-rw-r-- 1 tizio tizio 0 Mar 2 10:48 mio_file |
$
ln mio_file tuo_file
[Invio]
$
ls -l mio_file tuo_file
[Invio]
-rw-rw-r-- 2 tizio tizio 0 Mar 2 10:48 mio_file -rw-rw-r-- 2 tizio tizio 0 Mar 2 10:48 tuo_file |
Come si vede, con questa serie di operazioni si è giunti ad avere due file, apparentemente indipendenti, ma se viene modificato il contenuto di uno si vedono le modifiche anche sull'altro. Dal momento che i permessi e la proprietà dei file (UID e GID) sono informazioni contenute nell'inode, la modifica di questi si ripercuote su tutti i collegamenti.
Si può osservare il numero che appare dopo i permessi, due, che indica quanti riferimenti ha l'inode corrispondente. In pratica, quel numero indica quante voci puntano a quello stesso file. Non si può sapere facilmente quali siano gli altri riferimenti. Si può solo conoscere il numero dell'inode.
$
ls -l -i mio_file tuo_file
[Invio]
270385 -rw-rw-r-- 2 tizio tizio 0 Mar 2 10:48 mio_file 270385 -rw-rw-r-- 2 tizio tizio 0 Mar 2 10:48 tuo_file |
Come si vede, i due file hanno lo stesso inode (il numero che appare prima dei permessi), quindi sono lo stesso file.
Ogni directory contiene due riferimenti convenzionali: uno a se stessa e uno alla directory genitrice (.
e ..
). Si tratta di nomi di file a tutti gli effetti, che puntano agli inode della directory stessa e di quella precedente.
l'inode di una directory ha pertanto almeno due riferimenti: quello che serve a raggiungere la directory stessa, a partire dalla sua directory genitrice, e quello rappresentato dal punto singolo (la stessa directory).
Quando una directory ne contiene un'altra, allora il numero di riferimenti alla directory di partenza aumenta, perché la directory che si aggiunge ha un riferimento alla sua directory genitrice.
$
mkdir miadir
[Invio]
$
ls -l -d -i miadir
[Invio]
157715 drwxrwxr-x 2 tizio tizio 1024 Mar 2 11:22 miadir |
L'esempio mostra semplicemente il riferimento alla directory miadir/
contenuto nella sua directory genitrice. Si può provare a leggere il contenuto della directory appena creata.
$
cd miadir
[Invio]
$
ls -l -i -a miadir
[Invio]
157715 drwxrwxr-x 2 tizio tizio 1024 Mar 2 11:22 . 536615 drwxrwxr-x 3 tizio tizio 3072 Mar 2 11:22 .. |
Come si può osservare, il file indicato con un punto singolo (.) ha lo stesso numero di inode della directory miadir/
, cosa che spiega il motivo per cui una directory ha almeno due riferimenti (collegamenti fisici).
La directory genitrice, rappresentata dai due punti in sequenza (..
), ha tre riferimenti totali per il solo fatto che esiste questa directory (in pratica: i due riferimenti naturali, più questo, perché esiste questa directory).
|
Quando si creano collegamenti fisici, gli argomenti del comando ln, che rappresentano i file di origine, servono a individuare gli inode, a cui si vuole fare riferimento nella destinazione. Al contrario, quando si creano collegamenti simbolici, gli argomenti che rappresentano l'origine vengono trattati semplicemente come stringhe da riprodurre nei riferimenti della destinazione. Ignorando questo particolare, è facile fare degli errori senza comprenderne la ragione. Si osservino i comandi seguenti:
$
cd
[Invio]
$
pwd
[Invio]
/home/tizio |
$
mkdir prova
[Invio]
$
cd prova
[Invio]
$
pwd
[Invio]
/home/tizio/prova |
$
ln -s /bin/* .
[Invio]
Così facendo si creano dei collegamenti simbolici ai file e alle directory contenuti all'interno della directory /bin/
, con lo stesso nome che hanno nell'origine. Per esempio, il collegamento simbolico /home/tizio/prova/sh
punta precisamente a /bin/sh
. Si osservi invece la sequenza di comandi seguente:
$
cd /bin
[Invio]
$
pwd
[Invio]
/bin |
$
mkdir ~/prova
[Invio]
$
ln -s * ~/prova
[Invio]
Se si va nella directory ~/prova/
, si può osservare che i collegamenti puntano invece a loro stessi; per esempio, ~/prova/sh
punta a sh, ovvero a nulla che possa servire. Infatti, quando si dà il comando ln -s * ~/prova, si ottiene l'espansione dell'asterisco nell'elenco dei nomi (file e directory) contenuti nella directory corrente, che vengono usati tali e quali per la preparazione dei collegamenti. Pertanto, nella destinazione i collegamenti puntano poi ai loro stessi nomi.
Il programma di servizio cp (1) (Copy) copia i file:
cp [opzioni] origine destinazione |
cp [opzioni] origine... directory |
Se vengono specificati solo i nomi di due file, il primo viene copiato sul secondo, viene cioè generata una copia che ha il nome indicato come destinazione. Se il secondo nome indicato è una directory, il file viene copiato con lo stesso nome nella directory. Se vengono indicati più file, l'ultimo nome deve essere una directory e vengono generate le copie di tutti i file nella directory di destinazione. In mancanza di opzioni particolari, le directory non vengono copiate.
cp può essere pericoloso perché può sovrascrivere altri file senza preavviso. Per ridurre le possibilità di errori, conviene creare un alias in modo che cp funzioni sempre con l'opzione -i. Se poi si ha la necessità di sovrascrivere i file di destinazione, si può utilizzare l'opzione -f. |
|
Segue la descrizione di alcuni esempi.
$
cp -R /test/* ~/prova
[Invio]
Copia il contenuto della directory /test/
in ~/prova/
, copiando anche eventuali sottodirectory contenute in /test/
.
$
cp -R /test ~/prova
[Invio]
Copia la directory /test/
in ~/prova/
(attaccando test/
a ~/prova/
), copiando anche eventuali sottodirectory contenute in /test/
.
$
cp --parents aa/bb/cc miadir
[Invio]
Copia il file aa/bb/cc
in modo da ottenere miadir/aa/bb/cc
. Le directory intermedie, eventualmente mancanti, vengono create.
$
cp --no-dereference /test/* ~/prova
[Invio]
Copia il contenuto della directory /test/
in ~/prova/
, riproducendo i collegamenti simbolici così come sono nell'origine.
È molto importante comprendere la differenza tra le opzioni -r e -R. La seconda è quella che rappresenta meglio la ricorsività della copia, perché la prima tratta i file FIFO e alcuni file speciali come file normali. Per comprendere la cosa, si può procedere con l'esempio seguente, in cui si crea prima una directory, all'interno della quale si inserisce un file FIFO:
$
mkdir prova_1
[Invio]
$
mknod coda p
[Invio]
In questo modo, si ottiene il file FIFO prova_1/coda
. Volendo copiare la directory prova_1
in prova_2
, includendo il file FIFO coda
, si deve procedere nel modo seguente:
$
cp -R prova_1 prova_2
[Invio]
Al contrario, utilizzando l'opzione -r, la copia non si concluderebbe, perché questa resterebbe in attesa di dati dal file prova_1/coda
, come se fosse un file normale, per generare un file prova_2/coda
(di tipo normale), con tale contenuto.
Il programma di servizio ln (2) (Link) crea un collegamento tra file o tra directory:
ln [opzioni] origine destinazione |
ln [opzioni] origine... directory |
Se viene specificata un'origine e una destinazione, questa ultima diventa il nuovo collegamento che punta al nome indicato come origine (e può trattarsi anche di una directory). Se vengono specificati più nomi nell'origine, l'ultimo argomento deve essere una directory e si intende che al suo interno devono essere creati tanti collegamenti quanti sono i nomi indicati come origine. Se non viene specificato diversamente attraverso le opzioni, vengono creati dei collegamenti fisici e non dei collegamenti simbolici.
ln utilizza le variabili di ambiente VERSION_CONTROL e SIMPLE_BACKUP_SUFFIX nello stesso modo di cp.
|
Segue la descrizione di alcuni esempi.
$
ln -s /bin/ls ~/elenco
[Invio]
Crea il collegamento simbolico elenco
, all'interno della directory personale, che punta a /bin/ls
. Eseguendo il file ~/elenco
si ottiene in pratica di eseguire il comando ls.
$
ln /bin/ls ~/elenco
[Invio]
Crea il collegamento fisico elenco
, all'interno della directory personale, che punta a /bin/ls
. Eseguendo il file ~/elenco si ottiene in pratica di eseguire il comando ls.
$
ln -s /bin/* ~/
[Invio]
Crea una serie di collegamenti simbolici all'interno della directory personale per tutti i file contenuti in /bin
. Per ogni collegamento simbolico che viene creato, il percorso di questo risulta assoluto e inizia con /bin/
.
$
cd /bin ; ln -s * ~/
[Invio]
In questo esempio, rispetto a quanto mostrato in quello precedente, il comando di creazione dei collegamenti simbolici viene dato nel momento in cui ci si trova nella directory /bin/
, in riferimento a tutti i file della stessa. Quello che si ottiene nella directory personale dell'utente è la creazione di collegamenti simbolici diretti a loro stessi e perfettamente inutili.
$
ln -s /bin ~/binari
[Invio]
Crea il collegamento simbolico ~/binari
alla directory /bin/
. In questo modo, eseguendo cd ~/binari ci si ritrova in pratica in /bin/
.
Il programma di servizio install (3) copia i file attribuendo i permessi e le proprietà stabilite:
install [opzioni] origine... destinazione |
install [opzioni] -d directory... |
In pratica, si comporta in modo simile a cp con in più la possibilità di definire gli attributi dopo la copia e di creare tutte le directory necessarie. È usato tipicamente per l'installazione di programmi.
|
Il programma di servizio dd (4) (Data duplicator o Data dump) è un programma di copia a basso livello:
dd [opzioni] |
Le opzioni sono definite in modo strano rispetto ai normali programmi di servizio Unix, in quanto non sono prefissate dal solito trattino (-). Se tra le opzioni non vengono definiti i file di input o di output, si usano rispettivamente lo standard input e lo standard output.
Molte delle opzioni utilizzano un argomento numerico. Questi argomenti numerici possono essere indicati anche con l'ausilio di moltiplicatori posti subito dopo il numero stesso. La tabellina seguente riepiloga quelli di uso più comune; tenendo conto che sono disponibili altri moltiplicatori molto più grandi:
|
|
|
Il programma dd viene usato normalmente per riprodurre le immagini di dischetti, anche se nella maggior parte dei casi, con un sistema GNU/Linux è sufficiente usare cp. A questo proposito, vengono mostrati alcuni esempi.
#
dd if=disk.img of=/dev/fd0
[Invio]
In questo caso si trasferisce semplicemente il file disk.img
nel dischetto (inizializzato precedentemente). Nessun'altra indicazione è stata data, per cui si presume che il file sia adatto al formato di dischetto che si sta utilizzando.
#
dd if=disk.img of=/dev/fd0 obs=18k
[Invio]
Rispetto all'esempio precedente, si immagina di avere a disposizione un dischetto da 1 440 Kibyte (e naturalmente che il file-immagine sia adatto a questo tipo di dischetto). Un dischetto da 90 mm (3,5 pollici) con questo formato è composto da cilindri contenenti 18 + 18 settori di 512 Kibyte: 2 * 18 * 512 = 18 Kibyte. Specificando l'opzione obs=18k si intende fare in modo che dd fornisca al dispositivo /dev/fd0
blocchi di quella dimensione per facilitare l'operazione di scrittura.
#
dd if=disk.img of=/dev/fd0 obs=18k count=80
[Invio]
Rispetto all'esempio precedente, viene specificato il numero di blocchi da scrivere: 80, pari al numero dei cilindri. In questo modo, se il file in ingresso fosse più grande, non ci sarebbe alcun tentativo di superare tale limite.
Lo spostamento è una sorta di copia e cancellazione dell'originale. Attraverso questo meccanismo si ottiene anche il cambiamento del nome di file e directory: un cambiamento di nome puro e semplice non è possibile. Questo fatto deve essere considerato quando si valutano le conseguenze dei permessi attribuiti ai file e alle directory; inoltre, occorre tenere in considerazione il problema quando si valuta l'eventuale pericolosità di questo tipo di operazione: cambiare nome a un file in modo errato può provocare la sovrascrittura di un altro.
La cancellazione è sempre l'operazione più pericolosa. Nei file system Ext2 o Ext3 non è molto facile recuperare i dati cancellati. Piuttosto di cancellare, sarebbe meno pericoloso spostare temporaneamente i file in una directory che funge da cestino. Nella sezione 125.2.3 viene mostrato uno script in grado di gestire agevolmente una sorta di cestino del genere.
La cancellazione si ottiene normalmente eliminando la voce corrispondente all'interno di una directory e liberando l'inode corrispondente, mentre l'informazione rimane presente fino a quando lo stesso spazio viene riutilizzato nel disco. Quando si devono cancellare anche le tracce residue di un'informazione, occorre usare strumenti appositi che, prima di cancellare un file, lo sovrascrivono varie volte con dati più o meno casuali. Tuttavia, questa tecnica non funziona se la memoria di massa è organizzata in modo diverso dal solito per qualche fine, come può essere un sistema ridondante, un sistema che mantiene lo storico di tutti i cambiamenti apportati al file system o un sistema che si avvale della rete per la condivisione degli stessi dati.
Il programma di servizio mv (5) (Move) sposta i file o le directory:
mv [opzioni] origine... destinazione |
Se vengono specificati solo i nomi di due elementi (file o directory), il primo viene spostato o rinominato in modo da ottenere quanto indicato come destinazione. Se vengono indicati più elementi (file o directory), l'ultimo argomento deve essere una directory, all'interno della quale vengono spostati tutti gli elementi elencati. Nel caso di spostamenti attraverso diversi file system, vengono spostati solo i file normali, quindi: né collegamenti, né directory.
Il programma mv può essere pericoloso perché può sovrascrivere altri file senza preavviso. Per ridurre le possibilità di errori, conviene creare un alias in modo che mv funzioni sempre con l'opzione -i. Se poi si ha la necessità di sovrascrivere i file di destinazione, si può sempre utilizzare l'opzione -f. |
|
Il programma di servizio rm (6) (Remove) rimuove i file indicati come argomento:
rm [opzioni] nome... |
In mancanza dell'indicazione delle opzioni necessarie, non vengono rimosse le directory.
|
Segue la descrizione di alcuni esempi.
$
rm prova
[Invio]
Elimina il file prova
.
$
rm ./-r
[Invio]
Elimina il file -r
che inizia il suo nome con un trattino, senza confondersi con l'opzione -r (ricorsione).
$
rm -r ~/varie
[Invio]
Elimina la directory varie/
che risiede nella directory personale dell'utente, insieme a tutte le sue eventuali sottodirectory.
Il programma rm è pericolosissimo perché è potente e irreversibile. Gli errori più frequenti e disastrosi, sono causati da sbagli nella digitazione dei comandi o da cattiva valutazione dell'effetto di uno di questi. Ci sono tre cose da fare per ridurre i rischi di disastri:
|
Gli errori più frequenti da evitare sono descritti negli esempi seguenti.
$
rm prova *
[Invio]
Probabilmente, l'intenzione è quella di eliminare solo i file che iniziano con la parola prova, mentre in realtà viene inserito uno spazio involontario tra prova e l'asterisco. In tal modo, prima viene cancellato il file prova
e subito dopo tutto quello che si trova nella directory corrente.
$
rm -r .*
[Invio]
L'intenzione sembra essere quella di eliminare tutti i file e le directory nascoste (tutto ciò che inizia con un punto) contenute nella directory corrente. In realtà si individuano sì i file e le directory nascoste, ma con esse anche la directory corrente (.
) e quella precedente, ovvero la genitrice (..
)! A meno che il programma rm preveda espressamente questi casi in modo da evitare danni, si può ottenere la rimozione della directory corrente e anche della genitrice stessa.
Si osservi che spesso la directory personale dell'utente root è /root/
; se il comando appena mostrato viene dato da tale posizione, il cancellare la directory precedente (con tutto il suo contenuto), significa fare riferimento alla directory radice e quindi a tutto il file system.
Il modo migliore per non sbagliare utilizzando rm è quello di non usarlo. Quello che segue è un esempio di uno script che invece di cancellare sposta i file e le directory in una sorta di cestino:
|
L'esempio mostrato riproduce il percorso in cui si trovano i file a partire dalla directory che svolge il ruolo di cestino. In questo modo si possono creare delle collisioni, per esempio quando si tenta di sovrascrivere una directory con un file. Se si preferisce si può usare la versione alternativa che viene mostrata nel seguito, in cui l'inizio del percorso del cestino è ottenuto da una sottodirectory composta dalla data e dall'ora in cui è stata svolta l'operazione:
|
Il programma di servizio unlink (7) è probabilmente qualcosa di superfluo, ma esiste nei sistemi Unix, pertanto è incluso anche nei sistemi GNU. Il suo scopo è quello di cancellare il riferimento a un file, cosa che equivale alla cancellazione; tuttavia, in alcuni sistemi, questo programma può anche cancellare il riferimento a una directory, cosa che però non corrisponde alla cancellazione del suo contenuto, che così continua a esistere come inode, anche se può essere irraggiungibile attraverso un percorso. Per motivi di sicurezza, nei sistemi GNU, unlink non può essere usato con le directory.
unlink file... |
Il programma di servizio shred (8) serve a cancellare il contenuto di un file, in modo da renderne impossibile il recupero. Il programma shred esegue questo compito sovrascrivendo più volte i dati del file, con dati più o meno casuali:
shred [file] file... |
In condizioni normali, quando non si specifica qualcosa di diverso attraverso le opzioni, il file viene sovrascritto fino alla fine dell'ultimo blocco che lo contiene. Per blocco si intende l'unità minima di dati in base al contesto, che può essere il blocco del file system o il blocco dell'unità a blocchi, se si fa riferimento file di dispositivo il cui accesso è regolato in questo modo.
Dal momento che si può indicare un file su disco o un file di dispositivo, il programma non cancella il file alla fine della sovrascrittura, a meno che sia richiesto espressamente con le opzioni.
Per approfondire l'uso del programma, si può consultare la documentazione originale: info shred oppure la pagina di manuale shred(1). Si ricordi anche di verificare se, in base al proprio contesto operativo, l'uso del programma può produrre effettivamente il risultato atteso.
sdd(1) (9)
Si tratta di un programma simile, dal punto di vista funzionale, a dd, adatto in particolare al trasferimento integrale di dischi interi.
cstream(1) (10)
Si tratta di un programma simile, dal punto di vista funzionale, a dd, ma con una sintassi completamente diversa, che ha in più la capacità di limitare il flusso di dati a un valore stabilito.
Appunti di informatica libera 2006.07.01 --- Copyright © 2000-2006 Daniele Giacomini -- <daniele (ad) swlibero·org>
1) GNU core utilities GNU GPL
2) GNU core utilities GNU GPL
3) GNU core utilities GNU GPL
4) GNU core utilities GNU GPL
5) GNU core utilities GNU GPL
6) GNU core utilities GNU GPL
7) GNU core utilities GNU GPL
8) GNU core utilities GNU GPL
10) cstream software libero con licenza speciale
Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome copia_collegamento_spostamento_e_cancellazione.htm
[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [translators] [docinfo] [indice analitico]