[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]


203. Riproduzione speculare e trasferimento dati in modo automatico

Un servizio molto importante che può offrire un servente è la copia di informazioni già accessibili attraverso la rete. Il vantaggio di creare un sito speculare, ovvero un mirror, sta nel ridurre la concentrazione di richieste in una sola origine. Questo si riflette positivamente sia negli utenti locali, che ottengono le informazioni più rapidamente e con meno probabilità di essere esclusi per motivi di affollamento, sia nel servizio di origine, per il minore impegno richiesto al nodo e per il minore utilizzo della banda di collegamento alla rete.

In altre situazioni, quando gli utenti di una rete privata non hanno accesso all'esterno, la creazione di un sito speculare raggiungibile da questi utenti è l'unica possibilità per loro di ottenere tali informazioni.

203.1 Chi paga

L'utilizzatore normale dei servizi di Internet può non comprendere la differenza che c'è tra l'accedere a un servizio FTP rispetto a un altro, quando questi sono identici. La netiquette dice di usare il servizio più vicino, ma finché non si comprende il motivo è difficile che questa regola (come altre) venga rispettata.

Internet è fatta di tanti segmenti che collegano i vari nodi di rete, o host. I segmenti sono i cavi per i quali deve essere pagato un affitto all'azienda che può offrire tale servizio (in base alle norme dei rispettivi paesi). Ciò si traduce generalmente in un costo fisso, per il solo fatto di utilizzare il cavo, sia che vengano trasferiti dati, sia che resti semplicemente lì a disposizione. *1*

Tuttavia, anche se si tratta di un costo fisso, quando su quel cavo passano dei pacchetti non ne possono passare degli altri, ovvero, un flusso di dati rallenta il passaggio di altri dati.

Quando si ha la necessità di prelevare dalla rete grandi quantità di dati, tipicamente attraverso il protocollo FTP, è opportuno, in tutti i sensi, di cercare la fonte più vicina. La distanza in questione non si valuta attraverso uno spazio geografico, ma attraverso il numero di salti che i pacchetti devono fare, cioè il numero di nodi attraverso cui devono transitare. Minore è il numero di salti, minore sarà il numero di segmenti da utilizzare e così anche minore il costo per la comunità Internet. Questo dovrebbe chiarire anche l'utilità della presenza dei siti speculari nella rete.

203.2 Ramificazione dei siti speculari

Quando un servizio per il quale si predispongono dei siti speculari diviene molto importante e si vogliono realizzare molte di queste copie, si può porre il problema di non affollare il servizio di origine nel momento in cui i vari siti devono essere aggiornati.

Per risolvere questo problema conviene scomporre il sistema in più livelli, con un punto di origine, alcuni siti speculari di primo livello (o primari), e altri siti speculari che dipendono da quelli primari.

203.3 Sincronizzazione

I siti speculari sono utili in quanto contenenti una copia identica delle informazioni di loro competenza. L'allineamento, o sincronizzazione, avviene attraverso un controllo periodico e il trasferimento dei dati variati. Questa operazione non può essere fatta in modo continuo; si tratta di un lavoro di routine, da eseguire periodicamente a intervalli regolari.

La scelta della lunghezza di questi intervalli e del momento in cui eseguire questa attività è molto importante. In generale è bene definire che questo lavoro di sincronizzazione non può essere svolto ragionevolmente più di una volta nell'arco delle 24 ore, perché si tradurrebbe in un carico ingiustificato per il nodo dal quale si vogliono ottenere i dati. Dall'altra parte, l'orario in cui si eseguono queste operazioni dovrebbe essere scelto in modo da non interferire con altre attività, e quindi nel momento di minore carico, sia per il nodo a cui ci si collega, sia per quello all'interno del quale si esegue la riproduzione speculare.

203.4 Mirror

Mirror è un programma scritto in Perl che, attraverso il protocollo FTP, permette di duplicare una gerarchia di directory presente in un nodo remoto all'interno di quello locale. Il suo scopo è (ovviamente) quello di evitare la copia di file già presenti e ritenuti aggiornati. Per ottenere questo, viene comparata la data e la dimensione dei file.

Le fasi attraverso cui Mirror compie il suo lavoro possono essere schematizzate nei punti seguenti:

Mirror può essere usato fondamentalmente in due modi: fornendo tutte le informazioni necessarie attraverso la riga di comando (sconsigliabile) o configurando il file `mirror.defaults'. La scelta di impostare Mirror attraverso il suo file di configurazione è decisamente preferibile, dal momento che all'interno dello stesso possono essere indicate impostazioni differenti riferite a diversi «pacchetti» da replicare. In pratica, con questo termine (pacchetto), si intende fare riferimento a un blocco di dati da replicare nel sistema locale. Attraverso la riga di comando ci si può limitare a specificare il pacchetto o i pacchetti da sincronizzare.

Utilizzando Mirror, quando si deve indicare un percorso che fa riferimento a una directory, e non a un file normale, è bene aggiungere la barra obliqua finale (`/') per evitare ambiguità.

203.4.1 # mirror

mirror [<opzioni>] -g<indirizzo>:<percorso>

mirror [<opzioni>] [<file-di-configurazione>]

L'eseguibile `mirror' è ciò che svolge tutto il lavoro. Il suo scopo è quello di duplicare e mantenere sincronizzata una copia di una directory remota, attraverso il protocollo FTP. Le due sintassi rappresentate esprimono due modi differenti di utilizzo del programma: nel primo caso si indica il nodo e la directory remota direttamente sulla riga di comando, intendendo probabilmente che quella deve essere duplicata nel sistema locale a partire dalla directory corrente, nel secondo ci si avvale di un file di configurazione, più utile per l'utilizzo sistematico.

Il file di configurazione in questione può essere quello predefinito, `mirror.defaults', che dovrebbe trovarsi nella stessa directory del programma (è bene ricordare che il programma è uno script Perl e la sua collocazione non corrisponde a quella dei binari normali). Generalmente, per questioni di compatibilità con la gerarchia del filesystem standard di GNU/Linux, si colloca questo file nella directory `/etc/', mettendo un collegamento simbolico opportuno nella posizione in cui Mirror si aspetta di trovarlo.

Alcune opzioni

-p<pacchetto>

Questa opzione permette di indicare il «pacchetto» per il quale eseguire la riproduzione speculare. Si tratta di un nome che identifica una serie di opzioni, compresa l'indicazione del nodo remoto e della directory da duplicare, contenuto nel file `mirror.defaults' o in un altro equivalente definito nella stessa riga di comando.

Questa opzione può essere utilizzata più volte, a indicare così diversi pacchetti. Se questa opzione non viene usata e ci si avvale comunque del file di configurazione, si ottiene l'esecuzione dell'allineamento di tutti i pacchetti.

-n

Con questa opzione si simula l'allineamento. Lo scopo è solo quello di analizzare il funzionamento e di ottenere una traccia del procedimento che verrebbe svolto.

-g<indirizzo>:<percorso>

Con questa opzione si specifica l'indirizzo di un nodo remoto e un percorso da duplicare o allineare. Utilizzando questa opzione si presume che si voglia fare a meno del file di configurazione, come già descritto.

A seconda di come viene rappresentato il percorso, Mirror presume le intenzioni dell'utente. Precisamente, se il percorso termina con una barra obliqua normale (`/') si intende che si tratti di una directory e che tutto il suo contenuto debba essere duplicato, altrimenti, il percorso viene trattato come il nome di un file preciso o un modello che rappresenta file e directory diverse. È molto probabile che l'utilizzo normale di questo programma sia volto a duplicare una directory intera, comprese le sue discendenti, per cui è bene ricordare di utilizzare la barra obliqua alla fine del percorso.

-U[<file-delle-registrazioni>]

Attiva la registrazione dei carichi (upload). Se il nome del file non viene specificato, questo viene creato nella directory corrente (dipende da Mirror quale sia questa directory) utilizzando lo schema `upload_log.<giorno>.<mese>.<anno>'. Per evitare che tale file venga inserito all'interno della gerarchia che viene duplicata, sarebbe bene indicare sempre questo file, quando si usa questa opzione, facendo attenzione a specificare un percorso assoluto, che cioè parta dalla directory radice.

-k<nome>=<valore>

Una serie importanti di impostazioni sono definite attraverso valori da assegnare a delle variabili dichiarate nel file di configurazione. Per poter inserire tali indicazioni direttamente nella riga di comando occorre utilizzare questa opzione che, dopo `-k', permette di indicare un assegnamento di questo tipo.

Esempi

mirror -ptulipano

Avvia Mirror in modo che esegua la duplicazione o l'allineamento di quanto indicato all'interno del pacchetto `tulipano' definito all'interno del file di configurazione.

mirror -gdinkel.brot.dg:/pub/documenti/tulipano/

Avvia Mirror senza usare il file di configurazione, specificando che si vuole duplicare o allineare la directory `ftp://dinkel.brot.dg/pub/documenti/tulipano/' con quella corrente (del nodo locale) nel momento in cui si avvia il programma.

Come si vede, l'utente che esegue l'operazione non è `root', quindi i file vengono trasferiti attribuendo loro la proprietà dell'utente che esegue il comando. In questo caso, è più probabile che debba essere indicato il percorso necessario ad avviare l'eseguibile `mirror'.

203.4.2 /etc/mirror.defaults

Il file `mirror.defaults' è il mezzo normale per dirigere il comportamento di Mirror. Se l'installazione di Mirror è stata fatta correttamente e opportunamente, la sua collocazione dovrebbe essere la directory `/etc/'.

Il file si suddivide in configurazioni riferite a «pacchetti» differenti a cui si può fare riferimento utilizzando l'opzione `-p'.

Generalmente, questo file viene fornito con la configurazione per il pacchetto `defaults'. La configurazione corrispondente viene trattata come quella predefinita e va a sovrapporsi alle definizioni predefinite di Mirror stesso. In questo senso è opportuno verificare queste definizioni ed eventualmente modificarle, anche se per gli usi normali non dovrebbe essere necessario.

Quello che segue è un esempio del file `mirror.defaults' con la sola definizione di un pacchetto `default', molto più breve di quello che viene distribuito assieme all'applicativo.

# Il package default permette di definire una configurazione predefinita
# diversa da quella normale del programma mirror.

package=defaults
	local_dir=/home/ftp/pub/
	dir_mode=0755
	file_mode=0444
	user=0
	group=0
	do_deletes=true
	max_delete_files=50%
	max_delete_dirs=50%

Per prima cosa si osserva che i commenti sono prefissati dal simbolo `#' e che le righe vuote non vengono prese in considerazione.

Le direttive di questo file sono rappresentate da semplici assegnamenti di variabili, nella forma `<nome>=<valore>'. Tutto ciò che appare dopo il segno di uguaglianza viene «inserito» nella variabile indicata alla sinistra. Non si usano delimitatori, per cui, se si lasciano spazi dopo il simbolo di uguaglianza, questi verranno inseriti, tali e quali. Sono ammissibili anche assegnamenti nella forma `<nome>+<valore>', in tal caso, ciò che appare alla destra del segno `+' viene aggiunto al contenuto della variabile.

Se esiste la necessità di spezzare una direttiva per riprenderla nella riga successiva, si può usare il simbolo e-commerciale (`&') alla fine della riga che poi deve essere ripresa. La riga successiva verrà attaccata a quella precedente eliminando gli spazi anteriori (in tal modo si possono incolonnare i dati senza inconvenienti).

Gli elenchi di direttive sono raggruppati in «pacchetti» in cui la prima direttiva è sempre `package=...'. Nell'esempio questa direttiva viene mostrata allineata diversamente dalle altre, proprio per fare risaltare visivamente il suo ruolo importante.

Alcune variabili-direttive

package

La direttiva `package' apre un gruppo che rappresenta un pacchetto. Il file di configurazione dovrebbe contenere almeno il pacchetto `defaults', evidenziato dalla direttiva corrispondente `package=defaults'. Il valore assegnato a questa variabile deve essere un nome unico (senza spazi).

site

Il nome o l'indirizzo IP del nodo del quale si fa la riproduzione speculare.

remote_dir

Rappresenta la directory FTP remota, di cui si vuole fare la riproduzione speculare.

local_dir

La directory locale a partire dalla quale inizia la riproduzione speculare dei dati in questione.

remote_user

Permette di definire il nome dell'utente da utilizzare per la connessione FTP. Se non viene definito, si intende implicitamente che si tratti di `anonymous'.

remote_password

Permette di definire la password eventualmente necessaria per accedere al servizio FTP remoto. Se non si specifica, viene utilizzata quella convenzionale per l'accesso anonimo: <utente>@<host>.

do_deletes

Permette di definire se si intende che il programma cancelli i file locali che non ci sono più in quello di origine. Se non viene specificato, il valore predefinito è `false', che disattiva questa possibilità.

max_delete_files

Permette di indicare il numero massimo di file che possono essere cancellati, o in alternativa la percentuale se dopo il numero segue il simbolo `%'. In pratica, se nel nodo remoto, per quanto riguarda ciò di cui si fa la riproduzione speculare, sono stati eliminati più file di quelli specificati con questa variabile, tali file non vengono cancellati e si ottiene solo una segnalazione di errore.

Questo permette di evitare che il contenuto della riproduzione speculare venga cancellato quando l'origine viene spostata per qualche motivo, o semplicemente eliminata del tutto.

Il valore predefinito è `10%', per motivi di sicurezza.

max_delete_dirs

Permette di indicare il numero massimo di directory che possono essere eliminate automaticamente a seguito di variazioni nell'origine. Si comporta nello stesso modo della variabile `max_delete_dirs', e anche in questo caso, il valore predefinito è `10%'.

update_log

Questa variabile serve a definire il percorso di un file da utilizzare per annotare le operazioni svolte. Se il file esiste, le notizie vengono aggiunte a questo. Se non si indica un percorso assoluto, si intende un percorso relativo alla directory definita attraverso la variabile `local_dir'.

user

Permette di definire il nome o il numero UID dell'utente a cui attribuire la proprietà dei file e delle directory che vengono create. Se non viene specificato, viene usato l'utente che è proprietario del processo, ovvero colui che ha avviato Mirror. Se viene specificato qualcosa, è anche necessario che Mirror sia stato avviato con i privilegi dell'utente `root', altrimenti sarà impossibile cambiare la proprietà dei file e delle directory.

group

Permette di definire il nome o il numero GID del gruppo a cui attribuire la proprietà dei file e delle directory che vengono create.

file_mode

Permette di definire la modalità dei permessi attribuiti ai file creati localmente. Il valore predefinito è 0444, corrispondente ai soli permessi in lettura per tutti i tipi di utenti.

dir_mode

Permette di definire la modalità dei permessi attribuiti alle directory create localmente. Il valore predefinito è 0755, corrispondente ai permessi in lettura ed esecuzione per tutti e in più aggiunge il permesso in scrittura per l'utente proprietario (diversamente, Mirror stesso non avrebbe modo di modificarne il contenuto).

Mirror è altamente configurabile, e quanto qui riportato è solo una piccola parte delle variabili su cui si potrebbe intervenire. Per conoscere le altre caratteristiche si può consultare la pagina di manuale mirror(1)

Esempi

package=prova
	site=localhost
	remote_dir=/pub/
	local_dir=/tmp/prova/
	do_deletes=true
	max_delete_files=100%
	max_delete_dirs=100%
	update_log=/tmp/prova.log

L'esempio mostra un «pacchetto» definito solo per provare a eseguire la riproduzione speculare di quanto disponibile a partire da `ftp://localhost/pub/', collocandolo nella directory `/tmp/prova/'. Se la directory di destinazione non esiste, questa viene creata.

Inoltre: è concessa la cancellazione dei file che non si trovano più nell'origine; la cancellazione è concessa fino al massimo del 100%, sia per i file che per le directory; il file utilizzato per registrare le operazioni è `/tmp/prova.log'.

Per eseguire la riproduzione speculare nel modo specificato dal pacchetto `prova' si può utilizzare il comando seguente:

mirror -pprova

---------

package=ildp
	site=ftp.pluto.linux.it
	remote_dir=/pub/pluto/ildp/
	local_dir=/home/ftp/mirror/pluto/ildp/
	do_deletes=true
	max_delete_files=50%
	max_delete_dirs=50%
	update_log=/var/log/mirror.log

L'esempio appena mostrato è più verosimile e rappresenta la configurazione adatta a ottenere la riproduzione speculare di ILDP. In questo caso, si suppone che la directory di destinazione corretta nel proprio sistema sia `/home/ftp/mirror/pluto/ildp/'.

203.4.3 Riproduzione speculare di un'area HTTP

Finora si è parlato della riproduzione speculare di un'area FTP attraverso l'applicativo Mirror, realizzato in Perl. Per utilizzare questo programma allo scopo di ottenere la riproduzione speculare di un servizio HTTP occorre qualche trucco per aggirare l'ostacolo.

Evidentemente bisogna fare in modo che si possa accedere al servizio anche attraverso FTP, come un utente di tipo `guest' oppure come un utente normale. In entrambi i casi, nel nodo di origine, a cui si deve poter accedere per ottenere le varie riproduzioni speculari distribuite, occorre creare un utente apposito, la cui directory personale corrisponda all'inizio della gerarchia del servizio HTTP. Dal momento che questo utente non deve fare uso di una shell, è opportuno abbinargli il programma `false' al suo posto, avendo cura di includere tale programma tra le shell ammissibili nel file `/etc/shells' (altrimenti il servente FTP potrebbe rifiutarsi di accettare l'accesso con quel nominativo).

www:fq2243K5oN46M:33:33:Servizio HTTP:/home/httpd/html:/bin/false

L'esempio mostra una riga ipotetica del file `/etc/passwd' in cui si dichiara l'utente `www' necessario a permettere l'accesso all'area HTTP attraverso il protocollo FTP. Se si tenta di accedere in modo normale, non si riesce a ottenere una shell perché viene attivato al suo posto il programma `false' che termina subito l'esecuzione, impedendo l'accesso.

È bene chiarire che la proprietà dei file contenuti nella gerarchia da cui si diramano i documenti HTML deve essere di un utente e di un gruppo diverso dall'ipotetico `www', altrimenti si rischierebbe di consentire agli utenti FTP a cui si comunica la password di alterarne il contenuto.

Esempi

package=www-al
	site=linux.calion.com
	remote_dir=/AppuntiLinux/
	local_dir=/home/httpd/html/mirror/AppuntiLinux/
	remote_user=www
	remote_password=xxx
	do_deletes=true
	max_delete_files=50%
	max_delete_dirs=50%
	update_log=/var/log/mirror.log

L'esempio mostra la configurazione che era necessaria a definire la riproduzione speculare di Appunti Linux in HTML, quando qualche tempo fa la sua origine era presso il servente linux.calion.com. In base a questo esempio, è necessario accedere come utente `www' usando la password `xxx'.

203.4.4 Riproduzione speculare di servizi FTP non Unix

Il programma Mirror, per come è stato descritto, è in grado di accedere solamente a servizi FTP conformi agli standard dei sistemi Unix. Se si deve realizzare la riproduzione speculare di un servizio FTP differente, i listati che si ottengono con il comando `ls' (`LIST') sono diversi. In tal caso occorre leggere la documentazione originale di Mirror per trovare l'opzione giusta che permetta di accedere a tali FTP.

203.4.5 Attivazione automatica della procedura di allineamento

Come si può immaginare, per fare in modo che il sito speculare sia allineato regolarmente, si deve configurare il sistema Cron utilizzando gli orari più opportuni. L'esempio seguente mostra un pezzo del file crontab dell'utente `root' che avvia `mirror' per il pacchetto `ildp' alle 3:30 di ogni notte, e per il pacchetto `www-al' alle 4:30 di ogni notte.

...
# mirror
30 3 * * *  /usr/sbin/mirror -pildp > /dev/null
30 4 * * *  /usr/sbin/mirror -pwww-al > /dev/null

Per completezza viene mostrato come si dovrebbe trasformare l'esempio nel caso si tratti del file `/etc/crontab', in cui i comandi di Cron riportano anche l'indicazione dell'utente per conto del quale devono essere avviati.

# mirror
30 3 * * * root /usr/sbin/mirror -pildp > /dev/null
30 4 * * * root /usr/sbin/mirror -pwww-al > /dev/null

203.5 Riproduzione speculare attraverso il protocollo HTTP

La creazione di una riproduzione speculare di un servizio HTTP, attraverso lo stesso protocollo HTTP, è più complicato rispetto a quando è possibile usare il protocollo FTP. Infatti, i vari serventi HTTP sono predisposti in modo da nascondere quanto contenuto effettivamente nelle directory, basti pensare al fatto che convenzionalmente, quando si accede a un URI che fa capo a una directory, si ottiene quasi sempre il file `index.html'.

Per poter realizzare una riproduzione speculare in queste condizioni, occorre che il programma che si utilizza sia in grado di seguire i vari riferimenti ipertestuali contenuti nelle pagine HTML, a partire da quella dell'indice.

Il primo effetto collaterale di questo meccanismo sta nel fatto che poi si pongono dei problemi quando questi riferimenti si muovono all'indietro, in directory precedenti al punto scelto come partenza, oppure, peggio, si rivolgono a nodi differenti (reali o virtuali che siano).

Quando si incontrano dei riferimenti assoluti, contenenti un URI completo dell'informazione del nodo, si aggiunge un nuovo problema: si tratta dello stesso nodo, e quindi si possono modificare convenientemente, oppure si tratta di un nodo differente?!

Eventualmente, un programma del genere potrebbe prendersi cura di tentare di verificare la corrispondenza del nome contenuto nell'URI con quello dell'origine da cui si prelevano le informazioni, ma in tal caso, occorre tenere conto anche dei possibili alias che un nodo potrebbe avere nella rete. *2*

203.6 Wget

Il programma Wget è in grado di prelevare file utilizzando sia il protocollo HTTP che FTP. La sua caratteristica più importante è la capacità di operare sullo sfondo, senza bisogno di un terminale attivo. In questo senso, è anche insensibile al segnale `SIGHUP'. *3*

Wget è predisposto normalmente per il prelievo di un file singolo, e in questo senso, quando si utilizza il protocollo FTP per indicare un URI che fa riferimento a una directory, quello che si ottiene è un file HTML contenente l'indice di quella directory. La stessa cosa vale per il protocollo HTTP quando si fa riferimento a una directory per la quale il servente fornisce l'elenco del contenuto.

A seconda del fatto che si usi Wget per prelevare materiale attraverso il protocollo HTTP o FTP, il suo comportamento può essere differente; in particolare, quando si utilizza l'FTP, è possibile l'indicazione di caratteri jolly per fare riferimento a un gruppo di file.

La scansione ricorsiva deve essere richiesta in modo esplicito attraverso le opzioni o la configurazione, ma mentre nel caso dell'FTP si tratta di un processo abbastanza intuitivo attraverso cui si discendono le varie directory, quando si utilizza il protocollo HTTP significa seguire i riferimenti ipertestuali che si incontrano.

Quando si utilizza Wget per replicare un'area FTP particolare, la differenza fondamentale tra questo e il programma Mirror, sta nel fatto che Wget non è predisposto per eliminare i file che nell'origine sono stati rimossi.

203.6.1 Forma dell'URI

Per raggiungere gli oggetti che si vogliono scaricare si utilizzano degli URI, la cui forma può essere espressa dalle sintassi seguenti.

http://<host>[:<porta>]/[<percorso>]

ftp://<host>[:<porta>]/[<percorso>]

http://<utente>[:<password>]@<host>[:<porta>]/[<percorso>]

ftp://<utente>[:<password>]@<host>/[<percorso>]

Generalmente, con il protocollo HTTP, l'indicazione di un utente e di una password non è richiesta, e di conseguenza si salta. Nel caso del protocollo FTP è invece obbligatoria l'identificazione: quando queste informazioni non vengono fornite, né nell'URI, né nelle opzioni e nemmeno nei file di configurazione, si utilizza il noto utente anonimo (`ftp').

Come accennato, l'utente e la password possono essere forniti attraverso opzioni della riga di comando o direttive dei file di configurazione. A questo proposito, è importante osservare che si gestiscono due coppie diverse di nominativo-utente e password: una per il protocollo FTP e una per HTTP.

L'indicazione della password nella stessa riga di comando (nell'URI o nelle opzioni) è pericolosa perché risulta visibile nell'elenco dei processi in esecuzione.

203.6.2 File di configurazione

Wget può essere configurato attraverso due file di configurazione: `/etc/wgetrc' e `~/.wgetrc'. Il primo rappresenta la configurazione dell'intero sistema, e potrebbe essere collocato anche in altre posizioni del filesystem, a seconda della particolare distribuzione GNU/Linux che si utilizza; il secondo è il file di configurazione personalizzato. Le direttive contenute nel file di configurazione personale prendono il sopravvento su quelle della configurazione globale di sistema.

In ultima analisi, le opzioni della riga di comando prendono il sopravvento sulla configurazione.

Il contenuto di questi due file di configurazione segue le stesse regole sintattiche. I commenti sono preceduti dal simbolo `#', e così sono ignorate le righe bianche. Le direttive vengono espresse in forma di assegnamento di variabile, come indicato di seguito:

<nome> = <valore>

Per la precisione si distingue tra direttive che si riferiscono a modalità di funzionamento che possono essere attivate o disattivate, e in tal caso si assegnano le parole chiave `on' oppure `off', da quelle a cui deve essere assegnata una stringa contenente una qualche informazione. In particolare, in quest'ultimo caso, se si indica una direttiva in cui non si assegna alcun valore, si intende azzerare implicitamente quanto definito precedentemente per quella funzione di Wget (lo stesso ragionamento vale naturalmente anche per le opzioni della riga di comando).

203.6.3 $ wget

wget [<opzioni>] <uri>...

Wget si materializza in pratica nell'eseguibile `wget'. Come si può vedere dalla sintassi, l'uso di questo programma può essere molto semplice. È necessaria l'indicazione di almeno un URI, e in mancanza di altre indicazioni si intende ottenere solo la copia dell'oggetto a cui fa riferimento l'URI stesso (se si tratta di una directory di un FTP, si ottiene solo l'indice del contenuto).

La cosa più importante e delicata che può essere regolata attraverso le opzioni è la scansione ricorsiva del punto di origine, soprattutto quando l'URI di partenza fa riferimento al protocollo HTTP.

`wget' è esente da segnali `SIGHUP', e per questo è adatto particolarmente all'uso sullo sfondo (background), ma in tal caso è sempre meglio utilizzare `nohup' per sicurezza, perché alcune shell provvedono a eliminare i processi loro discendenti quando loro stesse terminano di funzionare.

La sintassi indicata è solo una semplificazione; in realtà, l'URI, pur essendo un'informazione necessaria, potrebbe essere fornito attraverso un file locale contenente uno o più riferimenti da scandire.

Alcune opzioni e direttive elementari

Di seguito vengono elencate alcune opzioni elementari, assieme alle direttive corrispondenti dei file di configurazione.

-o <file> | --output-file=<file>

Durante il suo funzionamento, vengono generati dei messaggi che normalmente sono emessi attraverso lo standard output. Per evitare che ciò avvenga si può utilizzare questa opzione in modo da creare il file indicato, mettendoci dentro tali messaggi. Se questo file dovesse esistere già, verrebbe cancellato.

-a <file> | --append-output=<file>

Invia nel file indicato i messaggi che altrimenti sarebbero destinati allo standard output, come con l'opzione `-o', con la differenza che i dati vengono aggiunti al file, se questo esiste già.

-v | --verbose

verbose = on

Attiva la modalità dettagliata in cui tutte le informazioni vengono emesse. A meno che il programma sia stato compilato in modo particolare, si tratta sempre della modalità predefinita.

-nv

verbose = off

Questa opzione, permette di disattivare la modalità dettagliata, facendo in modo che siano generati solo i messaggi essenziali.

-r | --recursive

recursive = on

Questa opzione permette di eseguire una scansione ricorsiva.

-l <n-livelli> | --level=<n-livelli>

reclevel = <n-livelli>

Specifica la profondità massima di ricorsione. Questa indicazione è fondamentale quando si vuole riprodurre un URI di tipo HTTP, perché i riferimenti possono andare in ogni direzione. Il valore predefinito è di cinque livelli.

-nc | --no-clobber

noclobber = on

In condizioni normali, quando si esegue una scansione ricorsiva allo scopo di prelevare una copia di un URI remoto, i file che dovessero essere già presenti nel sistema locale, verrebbero sovrascritti. Utilizzando questa opzione, si evita la sovrascrittura, ma soprattutto si evita che questi vengano caricati dal nodo remoto. Se si tratta di file HTML, cioè file da cui si può partire per un livello di ricorsione successivo, questi vengono semplicemente letti dal sistema locale.

In questo modo, questa opzione è importante per riprendere lo scarico di un URI remoto che in precedenza era stato interrotto.

-t <n-tentativi> | --tries=<n-tentativi>

tries = <n-tentativi>

Permette di definire un numero di tentativi per accedere alla risorsa. Se si utilizza il numero zero, o la parola chiave `inf', si intende fare in modo che `wget' tenti all'infinito.

-P <directory-locale> | --directory-prefix=<directory-locale>

dir_prefix = <directory-locale>

Permette di definire una posizione diversa dalla directory corrente per lo scarico dei file dall'URI remoto.

Esempi

Gli esempi seguenti partono dal presupposto che non sia stato predisposto alcun file di configurazione, per cui tutto quanto è descritto dalla riga di comando.

wget "http://dinkel.brot.dg/listino.html"

Preleva il file `listino.html' dall'URI `http://dinkel.brot.dg/listino.html', salvandolo nella directory corrente.

wget "ftp://dinkel.brot.dg/pub/listino.html"

Preleva il file `listino.html' dall'URI `ftp://dinkel.brot.dg/pub/listino.html', salvandolo nella directory corrente.

wget "http://dinkel.brot.dg/"

Genera il file `index.html' nella directory corrente, contenente quanto restituito dall'URI `http://dinkel.brot.dg/' (potrebbe trattarsi effettivamente dell'elenco del contenuto oppure di una pagina di ingresso).

wget "ftp://dinkel.brot.dg/"

Genera il file `index.html' nella directory corrente, contenente l'elenco del contenuto dell'URI `ftp://dinkel.brot.dg/'.

wget -r "ftp://dinkel.brot.dg/pub/progetto/"

Riproduce l'URI `ftp://dinkel.brot.dg/pub/progetto/' con tutto il contenuto della directory specificata e di quelle successive fino al massimo numero di livelli predefinito (cinque), generando il percorso `./dinkel.brot.dg/pub/progetto/...' nella directory corrente.

wget -r -l inf "ftp://dinkel.brot.dg/pub/progetto/"

Come nell'esempio precedente, ma viene riprodotto tutto il ramo `progetto/', senza limiti di livelli di ricorsione. Infatti, trattandosi di un URI FTP, non si pongono problemi a questo tipo di scelta, dal momento che la struttura ha fine prima o poi.

wget -r -l inf -nc "ftp://dinkel.brot.dg/pub/progetto/"

Come nell'esempio precedente, con la differenza che, se parte dei file contenuti nell'URI remoto sono già presenti localmente, questi non vengono prelevati effettivamente.

nohup wget -r -l inf -nc -o ~/mio_log (segue)
  "ftp://dinkel.brot.dg/pub/progetto/" &

Come nell'esempio precedente, con la differenza che il processo viene messo sullo sfondo (background) e viene controllato da `nohup', in modo da garantire che non sia interrotto quando la shell termina di funzionare. Inoltre viene generato il file `~/mio_log' con i messaggi emessi. *4*

wget -r "http://dinkel.brot.dg/progetto/"

Riproduce l'URI `http://dinkel.brot.dg/progetto/' con tutto il contenuto, in base ai riferimenti che vengono incontrati, fino al massimo numero di livelli predefinito (cinque), generando il percorso `./dinkel.brot.dg/progetto/...' nella directory corrente.

wget -r -nc "http://dinkel.brot.dg/progetto/"

Come nell'esempio precedente, ma i file già esistenti non vengono prelevati nuovamente e di conseguenza non vengono sovrascritti.

203.6.4 Scansione a partire da un file locale

`wget' permette di non indicare alcun URI nella riga di comando, utilizzando al suo posto l'inclusione di un file locale. Questa modalità viene utilizzata normalmente in modo congiunto a quella ricorsiva, e ciò che si ottiene è la scansione di tutti gli indirizzi URI contenuti nel file.

Il file può essere in formato HTML (è la cosa migliore), e in tal caso vengono seguiti i riferimenti ipertestuali, altrimenti può andare bene anche un file di testo contenente un elenco di indirizzi puri e semplici. Il problema si pone semmai quando il file indicato è in HTML, ma incompleto; in questo caso occorre specificare con un'opzione apposita che deve essere interpretato come HTML.

Gli indirizzi URI dovrebbero essere assoluti; se non lo sono, si può utilizzare un'opzione apposita per indicare l'URI di partenza, oppure, se si tratta di un file HTML, si può aggiungere un elemento speciale:

<base href="<uri>">

Tuttavia, è bene tenere presente che si tratta di un elemento non previsto nel DTD dell'HTML, quindi va usato solo in questa circostanza.

Opzioni e direttive

-i <file> | --input-file=<file>

input = <file>

Permette di indicare il file (HTML o un semplice elenco di URI) da utilizzare come punto di partenza per una scansione ricorsiva.

-F | --force-html

force_html = on

Richiede di interpretare il file indicato come HTML.

--base=<uri>

base = <uri>

Specifica esplicitamente un URI di partenza per i riferimenti relativi contenuti nel file.

Esempi

wget -r -i elenco.html

Scandisce tutti i riferimenti che trova nel file `elenco.html'.

wget -r -i elenco --force-html

Come nell'esempio precedente, con la differenza che il file `elenco' non viene riconosciuto automaticamente come HTML, e per questo è stata aggiunta l'opzione `--force-html'.

wget -r -i elenco --base="http://dinkel.brot.dg/"

Viene scandito il file `elenco' (il tipo di questo viene determinato in modo automatico), ma in più viene specificato che gli indirizzi relativi hanno il prefisso `http://dinkel.brot.dg/'.

203.6.5 Scansione ricorsiva

La scansione ricorsiva di un URI è ciò che genera i problemi maggiori nella gestione di Wget, e questo dovrebbe essere già stato capito dall'esposizione delle sezioni precedenti. La scansione ricorsiva di un URI di tipo FTP è abbastanza intuitiva, dal momento che si riferisce a un ramo di directory, mentre quando si tratta di un URI di tipo HTTP, questa ricorsione si basa sui riferimenti `HREF' e `SRC'; quando poi il file scaricato è di tipo `text/html', questo viene scandito alla ricerca di altri riferimenti da seguire.

Soprattutto quando si opera con il protocollo HTTP, è importante porre un limite alla ricorsione, dal momento che i riferimenti possono articolarsi in modi imprevedibili. Il numero massimo predefinito di livelli di ricorsione è di cinque.

A causa delle particolarità del protocollo HTTP, può essere conveniente limitare la scansione ricorsiva ai riferimenti relativi, oppure a quelli di un dominio particolare.

Quando la scansione ricorsiva è normale, cioè non si limita ai soli riferimenti relativi, si pone il problema di trattare convenientemente i riferimenti ipertestuali assoluti che puntano allo stesso nodo in cui si trovano. Infatti, può accadere che due nomi si riferiscano allo stesso nodo; in tal caso non ha senso sdoppiare i percorsi, anche perché si rischierebbe di duplicare lo scarico di alcuni file. Per risolvere questo problema, Wget interpella il sistema DNS in modo da verificare se si tratta della stessa macchina o meno.

Il vero problema nasce quando il servente HTTP distingue tra nodi virtuali differenti, a cui corrisponde però lo stesso indirizzo IP, in base all'uso di un diverso alias per raggiungere lo stesso elaboratore. In tal caso, occorre informare Wget di ignorare il sistema DNS e limitarsi al confronto letterale dei nomi dei nodi.

Opzioni e direttive

-L | --relative

relative_only = on

Fa in modo di seguire solo i riferimenti relativi, escludendo quindi qualunque URI completo dell'indicazione del nodo.

-np | --no-parent

no_parent = on

Permette di evitare che siano attraversate directory precedenti a quella dell'URI di partenza.

-X <elenco-directory> | --exclude <elenco-directory>

exclude_directories = <elenco-directory>

Permette di escludere un elenco di directory dalla scansione ricorsiva.

-nH

add_hostdir = off

Disabilita la creazione di directory locali prefissate dal nome del nodo di origine. Di solito, in presenza di una scansione ricorsiva di un URI, viene creata localmente una struttura di directory che riproduce il sistema remoto, a partire dal nome del nodo stesso.

Questa opzione è utile solo quando si è sicuri che i riferimenti non si sviluppano all'indietro (eventualmente attraverso l'uso di opzioni opportune), come quando si opera con URI di tipo FTP.

-nh

Disabilita il controllo DNS; in tal modo non viene verificato se due nomi di dominio appartengono in realtà allo stesso nodo.

-D <elenco-domini> | --domains=<elenco-domini>

domains = <elenco-domini>

Permette di definire un elenco di domini accettabili. In pratica, si permette a Wget di seguire i riferimenti a nodi differenti da quello di partenza, purché appartengano ai domini elencati.

-k | --convert-links

convert_links = on

In questo modo si ottiene di convertire i riferimenti assoluti in riferimenti relativi, limitatamente ai file scaricati effettivamente.

Esempi

wget -r -L -np "http://dinkel.brot.dg/progetto/"

Riproduce l'URI `http://dinkel.brot.dg/progetto/' con tutto il contenuto, in base ai riferimenti relativi che vengono incontrati, escludendo quelli che si riferiscono a posizioni precedenti alla directory `/progetto/', fino al massimo numero di livelli predefinito (cinque), generando il percorso `./dinkel.brot.dg/progetto/...' nella directory corrente.

wget -r -L -np "http://dinkel.brot.dg/progetto/" (segue)
  -X /progetto/img/,/progetto/x/

Come nell'esempio precedente, con l'aggiunta che non vengono riprodotte le directory `/progetto/img/' e `/progetto/x/'.

wget -r -D .brot.dg "http://dinkel.brot.dg/"

Riproduce l'URI `http://dinkel.brot.dg/progetto/' seguendo anche i riferimenti ad alti nodi purché appartenenti al dominio `.brot.dg'.

203.6.6 Selezione dei file in base al loro nome

Quando si scandisce un URI remoto in modo ricorsivo, è possibile definire i file da scaricare in base al nome. Nel caso particolare del protocollo FTP, si possono utilizzare i noti caratteri jolly nello stesso URI, mentre con il protocollo HTTP le cose cambiano perché ci si deve sempre affidare alla scansione dei riferimenti contenuti nelle pagine HTML.

Opzioni e direttive

-A <elenco-da-accettare> | --accept <elenco-da-accettare>

accept = <elenco-da-accettare>

In questo modo si può specificare un elenco di suffissi o di modelli espressi attraverso caratteri jolly riferiti a file che si vogliono scaricare. In pratica, si scaricano solo questi file, o meglio, gli altri che sono serviti per raggiungerli vengono rimossi successivamente.

-R <elenco-da-escludere> | --reject <elenco-da-escludere>

reject = <elenco-da-escludere>

In questo modo si può specificare un elenco di suffissi o di modelli espressi attraverso caratteri jolly riferiti a file che non si vogliono scaricare. Tutti gli altri file vanno bene.

Esempi

wget -r -A "*.gif,*.jpg" "http://dinkel.brot.dg/progetto/"

Salva localmente solo i file che terminano per `.gif' e `.jpg', provenienti dall'URI `http://dinkel.brot.dg/progetto/'.

wget -r -R "*.gif,*.jpg" "http://dinkel.brot.dg/progetto/"

Come nell'esempio precedente, con la differenza che viene scaricato tutto fuorché i file che terminano per `.gif' e `.jpg'.

203.6.7 Identificazioni e password

Si è già accennato al fatto che il nome dell'utente e la password eventualmente necessari per accedere a determinati servizi FTP e HTTP possono essere inseriti nello stesso URI. In alternativa si possono usare delle opzioni apposite o delle direttive dei file di configurazione.

È bene ricordare che solo inserendo le password all'interno del file di configurazione personale si può evitare che queste siano intercettate da altri utenti del sistema che potrebbero semplicemente leggere la riga di comando utilizzata per avviare l'eseguibile `wget'.

Opzioni e direttive

--http-user <utente>

http_user = <utente>

Permette di definire il nominativo-utente da usare per una connessione HTTP a un particolare URI che richiede l'identificazione.

--http-passwd <password>

http_passwd = <password>

Permette di definire la password da usare per una connessione HTTP a un particolare URI che richiede l'identificazione.

passwd = <password>

Permette di definire la password da usare per una connessione FTP.

203.6.8 Riproduzione speculare e informazioni data-orario

Quando si vuole riprodurre un URI remoto e si vuole mantenere la copia locale allineata con quella remota, la cosa più importante da verificare è la variazione dell'informazione data-orario degli oggetti remoti. In pratica, si vuole ottenere che:

Utilizzando una delle opzioni o delle direttive seguenti, si fa in modo che venga attuato questo meccanismo di aggiornamento, evitando così di ripetere ogni volta il prelievo di dati già esistenti localmente e presumibilmente aggiornati.

-N

--timestamping

timestamping = on

A fianco di quanto già visto, si inserisce l'opzione o la direttiva `mirror' che in pratica incorpora la ricorsione infinita assieme a `timestamping' e a `noclobber'.

-m | --mirror

mirror = on

L'esempio seguente serve a riprodurre nella directory corrente ciò che si dirama a partire da `http://dinkel.brot.dg/articoli/' senza seguire riferimenti in altri nodi, né all'interno di percorsi che si articolano da posizioni precedenti gerarchicamente. In particolare vengono trasformati i riferimenti in modo che siano solo relativi (senza l'indicazione del nodo)

wget --mirror --relative --no-parent -nH "http://dinkel.brot.dg/articoli/"

Questo esempio rappresenta l'utilizzo di Wget per ottenere la riproduzione speculare di un'area HTTP. Tuttavia, il difetto di questo approccio sta nel fatto che Wget non è in grado di verificare la scomparsa di file dall'origine, e quindi non può provvedere da solo alla loro eliminazione.

203.6.9 Particolarità con gli URI di tipo FTP

Alcune opzioni e direttive dei file di configurazione sono specifiche per l'uso con il protocollo FTP.

Opzioni e direttive

-c | --continue

Permette di riprendere il prelievo di un file (uno solo) continuando da dove l'operazione era stata interrotta precedentemente. Questa opzione può essere utilizzata anche con il protocollo HTTP, se il servente relativo è predisposto per questa funzionalità.

--follow-ftp

follow_ftp = on

In questo modo si consente si seguire un riferimento a un URI di tipo FTP, quando questo è contenuto in un file HTML.

-g {on|off} | --glob={on|off}

glob = {on|off}

Permette di attivare o disattivare la possibilità di utilizzare caratteri jolly. Generalmente, questa modalità è attivata in modo predefinito.

--retr-symlinks

retr_symlinks = on

Attivando questa modalità si fa in modo che, in presenza di collegamenti simbolici, vengano scaricati i file a cui questi fanno riferimento, invece di ricreare semplicemente tali collegamenti localmente.

203.6.10 Funzionalità varie

Altre funzionalità di Wget possono essere molto utili. Queste sezioni, tuttavia, non esauriscono la descrizione delle possibilità di Wget. Per approfondire il suo studio occorre consultare la sua documentazione, che normalmente è disponibile in forma di ipertesto Info: wget.info.

Opzioni e direttive

-Q <dimensione> | --quota <dimensione>

quota = <dimensione>

Permette di definire il limite massimo di spazio utilizzabile per i prelievi, quando questi sono fatti in modo ricorsivo. Il valore della dimensione viene espresso da un numero che rappresenta una quantità di byte. Se questo numero è seguito dalla lettera `k', indica unità in Kbyte, altrimenti, se è seguito dalla lettera `m', si riferisce a unità in Mbyte.

--spider

In questo modo si ottiene soltanto la verifica che l'URI indicato rappresenti un oggetto esistente. Se l'oggetto non esiste, o non è raggiungibile, l'eseguibile `wget' termina di funzionare restituendo un valore diverso da zero, e questo può servire per costruire degli script per la verifica di un elenco di URI, per esempio quello di un segnalibro di un programma di navigazione. Purtroppo, tale funzionalità non si adatta bene al protocollo FTP. *5*

-w <n-secondi> | --wait <n-secondi>

wait = <n-secondi>

Permette di stabilire un intervallo di tempo tra il prelievo di un file e il successivo. È molto utile per alleggerire il carico del sistema locale, di quello remoto, e dell'utilizzo della banda.

203.6.11 Realizzazione di un sito speculare HTTP con Wget

Dopo la descrizione che è stata fatta di Wget, si potrebbe analizzare la possibilità di realizzare una riproduzione speculare di URI di tipo HTTP. È già stato chiarito che quando Wget viene utilizzato per questo scopo, non si occupa di eliminare i file che dovessero essere stati rimossi dall'origine; per ottenere questo risultato occorre predisporre uno script apposito.

Per comprendere il senso della cosa si può osservare la forma del messaggio generato dall'eseguibile `wget' quando viene scaricato o verificato un file. Nel caso di un file che viene scaricato effettivamente si ottiene qualcosa di simile al testo seguente:

--18:19:13--  http://localhost:80/manual/index.html
           => `manual/index.html'
Mi sto connettendo a localhost:80...connesso!
HTTP richiesta inviata, aspetto la risposta... 200 OK
Lunghezza: 2,158 [text/html]

    0K -> ..                                                     [100%]

18:19:13 (702.47 KB/s) - `manual/index.html' salvato [2158/2158]

In alternativa, se il file esiste già e `wget' ritiene che sia già aggiornato:

--18:19:54--  http://localhost:80/manual/index.html
           => `manual/index.html'
Mi sto connettendo a localhost:80...connesso!
HTTP richiesta inviata, aspetto la risposta... 200 OK
Lunghezza: 2,158 [text/html]
Il file locale `manual/index.html' è più recente, non lo scarico.

Si può osservare in particolare la riga

           => `manual/index.html'

che contiene l'informazione del percorso corrispondente a questo file nel filesystem locale. Questa informazione può essere accumulata per conoscere quali sono i file aggiornati (indipendentemente dal fatto che sono stati scaricati o meno effettivamente), e confrontata con l'elenco di file che si trova effettivamente nel filesystem locale, permettendo l'eliminazione dei file superflui.

Di seguito viene proposto un programma in Perl che permette di realizzare una riproduzione speculare di un URI di tipo HTTP in pratica. Questo programma deve essere avviato quando la directory corrente è quella a partire dalla quale si vuole ottenere la riproduzione locale dell'URI remoto. `wget' viene usato con le opzioni `--mirror', `--no-parent' e `-nH', alle quali si potrebbe aggiungere eventualmente anche `--relative', se la situazione lo consente.

#!/usr/bin/perl
#=======================================================================
# mirror-http <URI> <opzioni-supplementari>
#
# Mantiene una copia speculare dell'URI indicato.
# In generale, l'URI deve essere una pagina HTML.
#=======================================================================

#-----------------------------------------------------------------------
# URI di partenza.
#-----------------------------------------------------------------------
$punto_di_partenza = $ARGV[0];

#-----------------------------------------------------------------------
# Directory corrente.
#-----------------------------------------------------------------------
$pwd = `pwd`;
chomp ( $pwd );

#-----------------------------------------------------------------------
# Opzioni per wget.
#-----------------------------------------------------------------------
$op_normali = "--mirror --no-parent -nH";
$op_supplementari = $ARGV[1];

#-----------------------------------------------------------------------
# Elenco attuale.
#-----------------------------------------------------------------------
@elenco_attuale = ();
$i_attuale = 0;

#-----------------------------------------------------------------------
# Elenco preesistente.
#-----------------------------------------------------------------------
@elenco_preesistente = ();
$i_preesistente = 0;

#-----------------------------------------------------------------------
# File trovato.
#-----------------------------------------------------------------------
$file_trovato = 0;

#-----------------------------------------------------------------------
# Record letto.
#-----------------------------------------------------------------------
$riga = "";

#-----------------------------------------------------------------------
# Avvia wget e preleva l'output.
#-----------------------------------------------------------------------
open ( WGET,
    "/usr/bin/wget $op_normali $op_supplementari $punto_di_partenza 2>&1 |" );

#-----------------------------------------------------------------------
# Legge il risultato delle operazioni di wget e ne estrae i nomi dei
# file aggiornati.
#-----------------------------------------------------------------------
while ( $riga = <WGET> ) {

    #-------------------------------------------------------------------
    # Se la riga letta contiene il simbolo «=>», allora contiene
    # l'informazione su un file aggiornato.
    #-------------------------------------------------------------------
    if ( $riga =~ m|=>| ) {
    
	#---------------------------------------------------------------
	# La riga contiene il percorso di un file locale che è stato
	# aggiornato: occorre estrarre questo nome (si trova delimitato
	# da «`» e «'»).
	#---------------------------------------------------------------
	$riga =~ m|`(.*)?'|;
	
	#---------------------------------------------------------------
	# Accumula nell'array.
	#---------------------------------------------------------------
	$elenco_attuale[$#elenco_attuale+1] = $1;
    }

    #-------------------------------------------------------------------
    # Riemette tutte le informazioni generate da wget.
    #-------------------------------------------------------------------
    print STDOUT "$riga";
}

#-----------------------------------------------------------------------
# Chiude il flusso abbinato all'esecuzione di wget.
#-----------------------------------------------------------------------
close ( WGET );

#-----------------------------------------------------------------------
# Avvia find per elencare i file esistenti effettivamente dopo
# l'aggiornamento con wget.
#-----------------------------------------------------------------------
open ( FIND, "/usr/bin/find . -type f -print |" );

#-----------------------------------------------------------------------
# Legge il risultato di find e accumula i nomi dei file.
#-----------------------------------------------------------------------
while ( $riga = <FIND> ) {

    #-------------------------------------------------------------------
    # Se la riga letta contiene il simbolo «./» iniziale, allora
    # contiene l'informazione su un file esistente.
    #-------------------------------------------------------------------
    if ( $riga =~ m|^\./| ) {
    
	#---------------------------------------------------------------
	# La riga contiene il percorso di un file locale:
	# occorre estrarre questo nome togliendo il prefisso «./».
	#---------------------------------------------------------------
	$riga =~ m|^\./(.*)|;
	
	#---------------------------------------------------------------
	# Accumula nell'array.
	#---------------------------------------------------------------
	$elenco_preesistente[$#elenco_preesistente+1] = $1;
    }
}

#-----------------------------------------------------------------------
# Chiude il flusso abbinato all'esecuzione di find.
#-----------------------------------------------------------------------
close ( FIND );

#-----------------------------------------------------------------------
# Scandisce i due array alla ricerca di file che devono essere
# cancellati.
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
# Scandisce prima l'array contenente i file che esistono fisicamente
# nel filesystem locale.
#-----------------------------------------------------------------------
for (
	$i_preesistente = 0 ;
        $i_preesistente <= $#elenco_preesistente ;
	$i_preesistente++
    ) {

    #-------------------------------------------------------------------
    # Azzera la variabile booleana che serve a indicare quando un file
    # deve rimanere.
    #-------------------------------------------------------------------
    $file_trovato = 0;

    #-------------------------------------------------------------------
    # Per ogni elemento dell'array, scandisce l'array contenente
    # l'elenco dei file aggiornati.
    #-------------------------------------------------------------------
    for (
	$i_attuale = 0 ;
        $i_attuale <= $#elenco_attuale ;
	$i_attuale++
    ) {

	#---------------------------------------------------------------
	# Verifica se i nomi corrispondono.
	#---------------------------------------------------------------
	if ( $elenco_preesistente[$i_preesistente]
	    eq $elenco_attuale[$i_attuale] ) {

    	    #-----------------------------------------------------------
	    # Il file deve rimanere, e questo ciclo interno termina.
    	    #-----------------------------------------------------------
	    $file_trovato = 1;
	    last;
	}
    }

    #-------------------------------------------------------------------
    # Verifica se deve cancellare il file.
    #-------------------------------------------------------------------
    if ( ! $file_trovato ) {

        #---------------------------------------------------------------
        # Cancella il file.
        #---------------------------------------------------------------
        unlink $elenco_preesistente[$i_preesistente];

        #---------------------------------------------------------------
        # Segnala l'eliminazione
        #---------------------------------------------------------------
        print STDOUT
	    "eliminato: $pwd/$elenco_preesistente[$i_preesistente]\n";
    }
}

#-----------------------------------------------------------------------
# Elimina le directory vuote.
#-----------------------------------------------------------------------
system ( "/usr/bin/find . -type d -exec rmdir \\{\\} \\; 2> /dev/null" );

#======================================================================

Se questo programma si chiama `mirror-http', supponendo di voler riprodurre l'URI `http://www.brot.dg/prove/', è `necessario' definire un file HTML di partenza. Di solito si tratta di `index.html', e se non è così occorre trovare un file che contenga dei riferimenti che permettano lentamente di raggiungere tutti gli altri file. Seguendo l'esempio, questo programma andrebbe usato nel modo seguente:

mirror-http "http://www.brot.dg/prove/index.html"

Quello che si ottiene è la riproduzione della directory `prove/' a partire dalla directory corrente e l'emissione attraverso lo standard output di tutti i messaggi, con l'aggiunta dell'indicazione dei file cancellati.

203.7 Netiquette

All'inizio del capitolo si è accennato alla netiquette. Dal momento che la gestione di un sito speculare è una cosa impegnativa, è bene ribadire i concetti più importanti.

  1. Prima di predisporre una riproduzione speculare di un sito qualunque occorre verificare eventuali restrizioni poste dall'amministratore del sistema di origine. Di solito si tratta di fare attenzione ai messaggi che appaiono al momento della connessione FTP o di quelli che si trovano nelle varie directory sotto forma di file che «chiedono» di essere letti (readme) o simili. Di sicuro potrebbe essere cortese una richiesta formale attraverso un messaggio di posta elettronica.

  2. Le operazioni di allineamento vanno svolte in orari in cui il servente remoto, e possibilmente anche quello locale, sono in relativa quiete.

  3. Periodicamente è bene verificare che le condizioni o le restrizioni poste dal sistema remoto non siano cambiate.

---------------------------

Appunti Linux 2000.04.12 --- Copyright © 1997-2000 Daniele Giacomini --  daniele @ pluto.linux.it


1.) Nel passato sono esistiti tipi di connessioni in cui l'affitto si pagava a un tanto a pacchetto (di dati). Ultimamente questa forma di contratto è in via di estinzione.

2.) Infatti, per esempio, `dinkel.brot.dg' potrebbe essere la stessa cosa di `www.brot.dg'.

3.) Alcune shell, quando concludono la loro attività, cercano di eliminare i processi loro discendenti, senza limitarsi a inviare un semplice `SIGHUP'. In tal caso conviene avviare `wget' attraverso `nohup'.

4.) Come si vede, il comando viene mostrato spezzato su due righe per un problema di spazio nella composizione tipografica. La barra obliqua inversa alla fine della prima riga, indica la continuazione. All'inizio della seconda riga appare il simbolo `>', per sottolineare il fatto che si sta continuando un comando.

5.) Il pacchetto ImageMagick, contiene un programma che non sembra appartenere al resto. Si tratta di `xtp', con il quale si può verificare la validità di un URI di tipo FTP.


[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]