Newsgroup: it.comp.os.linux.iniziare
Titolo: Script matto

Ciao secondo voi questo script crontabilizzato alle 23:55 di ogni
giorno cosa dovrebbe contenere?
#!/bin/sh
MAILDIR=/home/cart-021/Maildir/cur/
BCKMAILDIR=/home/cart-021/Maildir/bck
DATA=$(date --rfc-3339=date)
tar czvf $BCKMAILDIR/$DATA.tar.gz $MAILDIR$(ls --full-time $MAILDIR|
grep "$DATA"|awk -F " " '{print $9}') --remove-files
Se lo lancio da riga di comando funziona correttamente ossia mette nel
file tar tutte le mail che hanno come data di modifica quella corrente
(quella in cui lo lancio), se invece vado a vedere l'archivio generato
da crontab il giorno successivo vedo che l'archivio contiene solo 1
file con data $DATA delle ore 00:00.
Bho!!! Mi sto sicuramente perdendo qualcosa aiutatemi a trovarlo.

Alen192 wrote:

Sorvolando sul resto (e ce ne sarebbe parecchio da dire), per vedere cosa 
succede puoi mettere un set -x all'inizio dello script e farti mandare 
l'output via email, cosi' vedi cosa fa esattamente.


Mi puoi dire su cosa sorvoli?

Alen192 wrote:

Per prima cosa, ovvia, questi script di archiviazione vanno eseguiti dopo la 
fine del giorno a cui si riferiscono. Non conosco la tua situazione, ma tra 
le 23.55 e la mezzanotte potrebbero arrivare da n a n-mila mail. Cosa 
succede in quel caso? Nella migliore delle ipotesi, non hai archiviato 
alcune mail, che rimarranno per sempre non archiviate perche' il giorno 
successivo lo script non le selezionera'.
Altra cosa, tu stai facendo il backup di cur/ nella Maildir. Ma i messaggi 
nuovi di solito vanno in tmp/ e poi in new/, finche' qualcuno non li legge. 
C'e' qualcuno che alle 23.55 legge i messaggi?
Ok dirai, so per certo che i messaggi sono tutti letti, e non mi arriva 
nessun messaggio tra le 23.55 e mezzanotte. Benissimo, allora andiamo a 
vedere cosa fa lo script.
tar czvf $BCKMAILDIR/$DATA.tar.gz $MAILDIR$(ls --full-time $MAILDIR|
grep "$DATA"|awk -F " " '{print $9}') --remove-files
La shell esegue le sostituzioni (sia delle variabili che dei comandi tra 
$(...) o backquotes). Quindi la tua riga di comando diventa, una cosa alla 
volta:
step 1:
tar czvf /home/cart-021/Maildir/bck/$DATA.tar.gz $MAILDIR$(ls --full-time 
$MAILDIR|grep "$DATA"|awk -F " " '{print $9}') --remove-files
step 2:  (supponiamo ad esempio che $DATA sia 2009-10-08)
tar czvf /home/cart-021/Maildir/bck/2009-10-08.tar.gz $MAILDIR$(ls --full-
time $MAILDIR|grep "$DATA"|awk -F " " '{print $9}') --remove-files
step 3:
tar czvf /home/cart-021/Maildir/bck/2009-10-08.tar.gz 
/home/cart-021/Maildir/cur/$(ls --full-time $MAILDIR|grep "$DATA"|awk -F " " 
'{print $9}') --remove-files
A questo punto la shell esegue il comando tra $(...) e poi sostituisce 
l'output di tale comando nel comando principale
step 3.1:
ls --full-time $MAILDIR|grep "$DATA"|awk -F " " '{print $9}'
step 3.2:
ls --full-time /home/cart-021/Maildir/cur/|grep "$DATA"|awk -F " " '{print 
$9}'
step 3.3:
ls --full-time /home/cart-021/Maildir/cur/|grep "2009-10-08"|awk -F " " 
'{print $9}'
ls ha come output una lista di righe del tipo
-rw-r--r-- 1 mail mail  4546 2009-10-08 10:55:08.000000000 +0100 
1251280508.8909.m7UXB:2,S
-rw-r--r-- 1 mail mail 48369 2009-10-08 11:22:06.000000000 +0100 
1251282126.8909.ihuHI:2,RS
etc.
grep seleziona quelle che hanno "1009-10-08" (in questo caso tutte) e awk 
stampa il nono campo, ossia il nome del file. Quindi l'output finale della 
pipeline e' una cosa del genere:
1251280508.8909.m7UXB:2,S
1251282126.8909.ihuHI:2,RS
...
Questo e' il risultato del comando tra $(....). Ora siccome non e' tra apici 
doppi, la shell fa word splitting, ossia (semplificando) trasforma tutte le 
sequenze di spazi, newline e tab in un singolo spazio. Quindi l'elenco di 
cui sopra diventa in realta':
1251280508.8909.m7UXB:2,S 1251282126.8909.ihuHI:2,RS ...
Questo e' cio' che viene sostituito nel comando principale. Quindi 
riprendiamo da dove eravamo rimasti.
step 4:
tar czvf /home/cart-021/Maildir/bck/2009-10-08.tar.gz 
/home/cart-021/Maildir/cur/1251280508.8909.m7UXB:2,S 
1251282126.8909.ihuHI:2,RS <altri nomi qui> --remove-files
Quindi in definitiva gli argomenti che tar vede sono:
czvf 
/home/cart-021/Maildir/bck/2009-10-08.tar.gz
/home/cart-021/Maildir/cur/1251280508.8909.m7UXB:2,S 
1251282126.8909.ihuHI:2,RS 
...
--remove-files
--remove-files viene presumibilmente interpretato correttamente come 
opzione, e quindi tar interpreta il comando come: "crea l'archivio chiamato 
/home/cart-021/Maildir/bck/2009-10-08.tar.gz, mettendoci dentro i seguenti 
file: 
/home/cart-021/Maildir/cur/1251280508.8909.m7UXB:2,S
1251282126.8909.ihuHI:2,RS 
<altri nomi di file di mail presenti nella maildir>
e cancella i file quando li hai archiviati".
(Forse stai cominciando a vedere dov'e' l'errore)
Il primo file che tar deve mettere nell'archivio ha un full path, quindi 
viene trovato. Tutti gli altri file vengono indicati con un pathname 
relativo. Ma relativo a cosa? Qual e' la directory corrente in cui cron 
viene eseguito? Non so la risposta, ma sicuramente e' una directory che non 
contiene tali file. Quindi tar non li trova, e non li mette nell'archivio. 
Ecco spiegato perche' il tar contiene solo un file. Quando tu provi il 
comando lanciandolo da riga di comando, e dici che "funziona", sono 
praticamente sicuro che e' perche' lo lanci stando in cur/, e quindi quei 
pathname relativi vengono trovati.
Ho volutamente non parlato di altre cose tipo il quoting delle variabili e i 
nomi di file con spazi e altro. Lo script contiene diverse cose che sono da 
considerare "bad practice", anche se probabilmente in questo specifico caso 
la loro importanza non si apprezza perche' non si verificano le condizioni 
necessarie affinche' cio' accada. Comunque come regola generale:
- SEMPRE quotare le variabili, a meno di casi specialissimi (che comunque 
possono spesso essere evitati anch'essi), quindi usa "$PIPPO" e non $PIPPO.
- parsare l'output di "ls" e' una pratica quantomeno discutibile, anche se 
probabilmente in questo caso non crea grossi problemi;
- l'uso di grep e' ridondante, perche' awk puo' gia' fare la stessa cosa:
ls --full-time | awk -v data="$DATA" '$0~data{print $9}'
- in tema con il precedente, siccome $DATA contiene una data probabilmente 
non avrai problemi, ma in linea generale bisognerebbe sanificare il valore 
perche' potrebbe contenere caratteri che sono speciali nelle espressioni 
regolari, e proteggerli con degli escape;
- sempre riguardo awk, il print $9 nel tuo caso funziona, ma in generale 
assolutamente NO, perche' i nomi dei file potrebbero contenere spazi, e $9 
stamperebbe solo la prima "parola" del nome.

 file tar tutte le mail che hanno come data di modifica quella corrente
]zac[
Problemi di PATH dei comandi, permessi di accesso, shell diversa usata,
ecc. .
In ogni caso di conviene inserire un pezzo alla volta dello script, una
volta totalmente sicuri che lo script funziona, aggiungere un altro pezzo e
verificarlo per bene, una volta circoscritto il punto dovrebbe essere
possibile fare delle ipotesi del problema e testarle.