Newsgroup: it.comp.os.linux.iniziare
Titolo: eliminare cartelle di backup

su una macchina linux tramite rsync vengono fatti durante la notte i 
backup di alcuni server.
la struttura e'
/var/backup/server1/2010-05-01/...
/var/backup/server1/2010-05-02/...
/var/backup/server1/2010-05-03/...
/var/backup/server2/2010-05-01/...
/var/backup/server2/2010-05-02/...
/var/backup/server2/2010-05-03/...
ecc...
volevo fare  uno script per eliminare i backup che sono piu' vecchi di 
un certo numero di giorni ma le mie conoscenze sono decisamente troppo 
scarse ...
mi potrebbe bastare qualche buon esempio..
Grazie 

 Davide
grazie, se appena appena riesco a capire che cosa fa' ci provo... :-)

 Davide
Troppa grazia !!!
solo che mi dice "missing argument to -exec


cappero e cipolla, nemmeno a copiare sono buono !!!
non avevo lasciato uno spazio dopo la graffa !
Avanzi una pinta di birra !

 ...
find scende ricorsivamente nelle directory, rm scende ricorsivamente
nelle directory; mi viene in mente una parola (anzi due ed in inglese):
/race/ /condition/ . 
Non serve fare il debug né provare per capire che appoggiare  la mano 
sull'incudine è pericoloso.
Tra le tante soluzioni Io propongo:
find /var/backup/ -depth -maxdepth 1 -type d -name 'server*' \
  -ctime +$NUMERO_GIORNI \ -exec -rm -fr {} \;
-depth è inutile in questo caso ma conviene programmare in maniera 
difensiva e metterla lo stesso. Ricordo che -depth deve essere usata 
sempre quando si cancella qualcosa.
Infine ctime: non è il tempo di creazione e se si usa come fosse il tempo 
di creazione si accetta anche la possibilità di bug insidiosi.
 

 find /var/backup/ -ctime +NUMGIORNI -type d -exec rm -fr {} \;
E che succede se sotto i vari "2010-*" hai delle directories la cui data di 
creazione e` piu` vecchia del NUMGIORNI ma il cui contenuto deve essere salvato 
nel backup? Dipende se il backup e` un file singolo oppure un insieme di 
directories (con data originale). Io sarei andato sul sicuro e avrei fatto:
find /var/backup/* -ctime +NUMGIORNI -type d -maxdepth 1 -exec rm -fr {} \;
Cosi` pero' uno potrebbe perdere tutti i backups se la procedura non gira per 
piu` di NUMGIORNI... Io farei in modo di conservare gli ultimi TOT backup e non 
i backup piu` vecchi di TOT giorni. Qualcosa del tipo:
#!/bin/bash
KEEP=3
while read f; do
   n=0
   while read d; do
     [ -d "$d" ] || continue
     (( ++n > KEEP )) && rm -rf "$d"
   done < <( ls -t "$f" )
done < <( find /var/backup/* -type d -maxdepth 0 )
Questa procedura (da provare) dovrebbe levare tutti i backup eccetto i 3 piu` 
recenti, indipendentemente dalla loro data. Lo so che non era questa la 
richiesta originale, ma io farei cosi`.
Ciao,
-- 
        Roberto Divia`              Love at first sight is one of the greatest
Dep:PH Bat:53 Mailbox:C02110      labour-saving devices the world has ever seen
Route de Meyrin 385               ---------------------------------------------
Case Postale                                Phone:  
+41-22-767-4994
CH-1211 Geneve 23 CERN                      Fax:    
+41-22-767-9585
Switzerland                                 E-Mail: 
Robert...@cern.ch

   -ctime +$NUMERO_GIORNI  -exec -rm -fr {} ;
Nella tua, come nelle altre soluzioni, leggo sempre rm -fr
e non riesco a comprendere l'uso dell'opzione "-f".
Leggendo nel man trovo:
OPTIONS
-f, --force
ignore nonexistent files, never prompt
-i
prompt before every removal
-I
prompt once before removing more  than  three  files,  or  when removing
recursively.  Less intrusive than -i, while still giving protection
against most mistakes
Puoi spiegarmi per cortesia? In particolar modo "nonexistent files".
Da ignorante, per maggior sicurezza io avrei usato rm -Ir
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 tempo di creazione si accetta anche la possibilità di bug insidiosi.
Mi chiedevo: vista la struttura di directory creata da rsync, e dati
i nomi delle directory, sfruttarli e cancellare direttamente in base a
loro sarebbe sconsigliabile?
Pensavo si potrebbe far fare a cron ogni giorno qualcosa come:
find /var/backup/server*/ -depth -maxdepth 1 -type d -name $(date -d "30 days ago" +%F) -exec rm -fr {} \;  
E, per ripulire eventuali rimasugli, ogni mese qualcosa come:
find /var/backup/server*/ -depth -maxdepth 1 -type d -name $(date -d "2 months ago" +%Y-%m)* -exec rm -fr {} \;
e ogni fine anno qualcosa come:
find /var/backup/server*/ -depth -maxdepth 1 -type d -name $(date -d "last year" +%Y-)* -exec rm -fr {} \;
Avrebbe senso?
-- 
Bye, Lem
Ceterum censeo ISLAM esse delendum
____________________________________________________________________________
Non sprecare i cicli idle della tua CPU: 
http://boinc.berkeley.edu/index.php

 tempo di creazione si accetta anche la possibilità di bug insidiosi.
Mi chiedevo: vista la struttura di directory creata da rsync, e dati


 Avrebbe senso?
No, mi sembra un pastrocchio incredibilmente complicato che 
non funziona e che ripeti inutilmente per tre volte.

 processando in un altro modo si'.
A volte mi chiedo se hai mai letto un manuale o  l'info di find e se 
hai il cervello sempre collegato ed acceso.
Quando anche fosse stato vero che l'unico problema sarebbero stati
i messaggi di errore spurii di find questo avrebbe comportato una 
perdita di tempo.
Fosse stato un compito da fare una sola volta non avrebbe avuto 
neanche senso replicare ma poiché si tratta di backup, è un compito 
ripetitivo, che probabilmente sarà schedulato con cron e ripetuto 
tutti i santi giorni e forse su più macchine allora non perdere tempo 
è essenziale.
Ma ancor di più è programmare bene è essenziale in questo caso:
find non è la soluzione migliore, cancellare i backup solo in base 
alla loro età non è la politica migliore e sopraattutto ctime, il tempo
di creazione, non indica il momento di creazione della directory
e questo può causare un bug grande come un grattacielo.

 ...
Scusate: regole grammaticali e fretta non vanno tanto 
d'accordo e possono scappare degli svarioni.

 sono i tuoi backup dopo tutto.
Avresti fatto meglio a rispoindere ``rm / -fr'' o ``mke2fs /dev/sdxx'';
fanno più BAFH.

 Non e' quello che aveva chiesto lui.
in realta' era proprio quello che avevo chiesto ...

 era questa la richiesta originale, ma io farei cosi`
---------------------------------------------------------------------------------------------------
ho provato ad eseguire lo script
#! /bin/bash
KEEP=6
while read f; do
    n=0
    while read d; do
     [ -d "$d" ] || continue
        (( ++n > KEEP )) && rm -rf "$d"
    done < <( ls -t "$f" )
done < <( find /var/backup/file_server/* -maxdepth 0 )
-------------------------------------------------------------------------------------
ma dice:
cancella: line 8: syntax error near unexpected token `<'
cancella: line 8: `    done < <( ls -t "$f" )'
e non sono in grado di capire dove sta' l'errore :-( 

 in realta' era proprio quello che avevo chiesto ...
Guarda... persino Roberto Divià ha ammesso esplicitamente che la sua
soluzione non soddisfaceva la tua richiesta originale... :)


 soluzione non soddisfaceva la tua richiesta originale... :)
la richiesta iniziale era decisamente formulata male, la soluzione 
proposta di tenere gli ultimi 3 salvataggi e' quella corretta 


Strano... Prova a fare sulla linea di comando:
read t < <( echo Test )
Deve funzionare. Da me funge.
Al limite, posta il tuo script (cut-and-paste) che lo proviamo.
Quel che non capisco e` che le linee 8 e 9 usano la stessa sintassi. La 8 va, la 
9 no. Potrebbe essere in errore di trascrizione.
Ah, per favore dacci anche il tuo "bash --version"...


prima ringrazio per la pazienza e il prezioso aiuto !!
ecco qua
#! /bin/bash
KEEP=6
while read f; do
    n=0
    while read d; do
     [ -d "$d" ] || continue
        (( ++n > KEEP )) && rm -rvf "$d"
    done < <( ls -t "$f" )
done < <( find /var/backup/file_server/* -maxdepth 0 )
backup cron.daily # bash --version
GNU bash, version 3.2.17(1)-release (i686-pc-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
backup cron.daily #


Tutto sembra a posto. Prova a cancellare la riga 8 e a riscriverla a mano.
done < <( ls -t "$f" )
Al limite, leva lo spazio tra "done" e "<"...


 ha scritto nel messaggio 
news:hu0c8o$2pm$1...@news.eternal-september.org...



Va bene, andiamo sul classico allora...
while read d; do
...
done < <( ls -t "$f" )
cambialo in
ls -t "$t" | while read d; do
...
done
Ciao,
   -- Roberto


 ha scritto nel messaggio 
news:hu0da0$79s$1...@news.eternal-september.org...


 done < <( find /var/backup/* -type d -maxdepth 0 )
Prova 
#!/bin/bash
KEEP=3
find /var/backup -maxdepth 1 -mindepth 1 -type d | 
  while IFS='' read -r file
    do
      n=0
# questo è uno dei pochi casi dove ls in un pipe potrebbe essere utile
      ls -t "$file" |
      while IFS='' read -r directory
        do
# questo controilo mi sembra inutile: già find fa questo test
          if  ! [ -d "$directory" ]
            then
             ++n   # 
              if n> $KEEP
                then
                rm  -rf "$directory"
              fi
          fi  
        done 
      done
Prima di tutto la bash non è il C: espressioni come (++n < m) in C sono 
pericolose, negli altri linguaggi sono da evitare.
Riguardo alla sostituzione dei comandi non è portabile, già con la bash 
non funziona sempre e va usata quando serve realmente, non come 
sfoggio di sapere.
Infine gli operatori || e && : sono indispensabili ma non vanno usati al 
posto degli ``if ... then ... '': è una cattiva pratica.
Post scriptum: mi son limitato a togliere gli orrori, non ho provato né
ho analizzato cosa fa questo script.

 ho analizzato cosa fa questo script.
:-o 

Addì  lunedì 31 maggio 2010 16:27 ES scrisse:

Che vuoi, mi fido.

 ha scritto nel messaggio 
news:4c03c96d$0$18662$4faf...@reader3.news.tin.it...

sara', ma anche cosi non funziona... c'e' qualche errorino di sintassi 
direi

Addì  lunedì 31 maggio 2010 16:38 ES scrisse:

#! /bin/bash
KEEP=3
find /var/backup -maxdepth 1 -mindepth 1 -type d | 
  while IFS='' read -r file
    do
      n=0
# questo è uno dei pochi casi dove ls in un pipe potrebbe essere utile
      ls -t "$file" |
      while IFS='' read -r directory
        do
# questo controilo mi sembra inutile: già find fa questo test
          if  !  [ -d "$directory" ]
            then
             (( ++n )) 
              if (( n > $KEEP ))
                then
                rm  -rf "$directory"
              fi
          fi  
        done 
      done
A parte la svista della valutazione delle espressioni (le doppie 
parentesi) non ho voglia di fare il debug di un programma scritto 
da altri. Del resto mi pare che tu abbia già risolto _prima_ del 
mio post
 

 mia totale incapacita'
Io un problema del tutto analogo l'ho risolto in questo modo:
#!/bin/bash
# routine che identifica tutti i file piu' vecchi di x giorni nella
# cartella indicata.
# parametri:
# 1) giorni;
# 2) azione;
# 3) directory.
# ATTENZIONE: indicare solo la DIRECTORY all'interno della quale
# effettuare la ricerca. Il singolo punto identifica la directory
# corrente.
# Come azione, indicare r, -r o --remove per effettuare la rimozione
# dei file trovati; qualsiasi altra cosa per effettuarne semplicemente
# la lista.
GIORNI=$1
AZIONE=$2
PERCORSO=$3
SYSTIME=`date +%s`
SECS=$(( $GIORNI * 86400 ))
MINTIME=$(( $SYSTIME - $SECS ))
for OGNI in $PERCORSO/*; do
   if [ -f $OGNI ]; then
      DATI=`stat -c "%n %Y" $OGNI`
      NOMEFILE=`echo $DATI | cut -f 1 -d \ `
      ORAMOD=`echo $DATI | cut -f 2 -d \ `
      if [ $ORAMOD -le $MINTIME ]; then
         if [ "$AZIONE" == "r" \
              -o "$AZIONE" == "-r" \
              -o "$AZIONE" == "--remove" ]; then
            rm -f $NOMEFILE
         else
            echo $NOMEFILE
         fi
      fi
   fi
done
Nel mio caso mi baso su "stat", perché sono file di log che vengono
generati e mai più modificati. In ogni caso, venissero modificati, al
peggio restano per più tempo, per cui non si perde niente.
Per non aver problemi con gli orari, converto tutto in orario di sistema
(secondi a partire dal 1 Gen '70) e lo confronto con l'orario di sistema
attuale.
Questo script elimina *file*, ma puoi molto facilmente riadattarlo per
eliminare delle directory, così come puoi basarti sullo stesso nome
della directory se essa stessa rappresenta un orario.
Fatto salvo il discorso che nel caso di una directory, perdi il
controllo sui file in essa contenuti.
Per stare dalla parte del frumentone, come si suol dire, io cancellerei
i singoli file directory per directory, e poi tenterei una cancellazione
"pulita" della directory con rmdir: se la cartella è vuota a quel punto
si elimina, viceversa resta lì con quel che ha dentro.
-- 
Massimo Bacilieri AKA Crononauta

 cancella: line 8: `    done < <( ls -t "$f" )' 
Lo spiega anche l'errore!   Dopo il primo "<" deve esserci una stringa 
di caratteri, Cioè l'output di 'ls'.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   < 
http://giovanni.homelinux.net/
 >

 La combinazione "<(" non ha alcun valore sintattico.
Man bash (e provare prima di scrivere).
-- 
Cio' che si vede, e'.

 
Appunto!  ho provato e tu lo hai fatto?
funziona solo con:
......
done < $( ls .... )
Non so a cosa serva <( ma sul mio sistem NON funziona in nessun caso.


 La combinazione "<(" non ha alcun valore sintattico.
Ma per favore!


 Non so a cosa serva <( ma sul mio sistem NON funziona in nessun caso.
Azz cosa usi, bash 1? Se e' non-preistorica, <( funziona. (E il tuo 
suggerimento e' *sbagliato* in ogni caso, ma che te lo dico a fare).


 Ma per favore!
Su quale versione di bash funziona?
3.2.29(2)-release
../tst: line 7: syntax error near unexpected token `<'
../tst: line 7: `done <  <( ls /bin )'


 Su quale versione di bash funziona?
lem@lappybaby:~$ bash --version
GNU bash, versione 4.1.5(1)-release (x86_64-pc-linux-gnu)
[...]
Vedi "Sostituzione di processo" in
http://www.pluto.it/files/ildp/man/man1/bash.1.html
Come esercizio, suggerisco di riflettere su:
cat $(ls)
cat <<< $(ls)
cat < <(ls)
ls
for i in $(echo pippo pluto); do echo $i; done
for i in <(echo pippo pluto); do echo $i; done
read t < <(echo pippo) && echo $t
read t <(echo pippo) && echo $t
echo $(echo pippo)
echo <(echo pippo)
Etc. etc. etc.: ci si può sbizzarrire. :)


 Etc. etc. etc.: ci si può sbizzarrire. :)
$ cat test.sh  ##-------------------
#!/bin/sh -x
cat $(ls)
cat <<< $(ls)
cat < <(ls)
ls
for i in $(echo pippo pluto); do echo $i; done
for i in <(echo pippo pluto); do echo $i; done
read t < <(echo pippo) && echo $t
read t <(echo pippo) && echo $t
echo $(echo pippo)
echo <(echo pippo)
$ test.sh  ##-------------------
++ ls
+ cat pippo test.sh
English text
#!/bin/sh -x
cat $(ls)
cat <<< $(ls)
cat < <(ls)
ls
for i in $(echo pippo pluto); do echo $i; done
for i in <(echo pippo pluto); do echo $i; done
read t < <(echo pippo) && echo $t
read t <(echo pippo) && echo $t
echo $(echo pippo)
echo <(echo pippo)
+ cat
++ ls
pippo test.sh
./test.sh: line 5: syntax error near unexpected token `<'
./test.sh: line 5: `cat <
'
$   ##-------------------
Bene. <(...) è valido.  Ho scritto una cazzata.
Sai spiegare per quale motivo non funziona?


 Sai spiegare per quale motivo non funziona?
Per usare la sostituzione del processo deve essere soddisfatta
una delle seguenti possibilità:
1) Il sistema operativo supporta le /named/ /pipe/ dette anche FIFO
2) Il sistema operativo supporta /dev/fd* per gestire i file aperti
3) Il programmatore  sa programmare con la bash


Ho chiesto perché non funzionano gli esempi forniti!
E tutte le tre condizioni sono soddisfatte.  Le man pages le so 
leggere anche io.


 leggere anche io.
Dissento su entrambi i punti.
"Guarderete e non vedrete, udrete e non ascolterete"
http://tldp.org/LDP/Bash-Beginners-Guide/Bash-Beginners-Guide.pdf

 Sai spiegare per quale motivo non funziona?
Sarï¿œ banale, ma hai provato a vedere che risponde un
ls -la /bin/sh
-- 
           |Save our planet!
    Ciao   |Save wildlife!
   roberto |For your E-MAIL use ONLY recycled Bytes  !!
           |roberto poggi   
rpo...@softhome.net

 
Se non sai rispondere non devi vergognarti.
Non è necessario scrivere delle banalità.



Se non sai rispondere non devi vergognarti.
Non è necessario scrivere delle banalità.
Ciao


 Non ï¿œ necessario scrivere delle banalitï¿œ.
Sarebbe la prima volta che qualcuno NON sta usando bash come
link a /bin/sh  vero, genio?
Adieu.


 Non è necessario scrivere delle banalità.
Nemmeno scrivere cazzate e' necessario.


 
Se proprio hai voglia di scrivere cazzate follow-up to:
it.fan.culo


 
Se riportare gli errori in uno script suggerito e chiedere lumi ti 
sembra una cazzata!
O sai rispondere oppure followe up: it.fan.culo


 sembra una cazzata!
Io un'occhiata a cosa punta /bin/sh ce la darei comunque. Poi cazzi tuoi, e' 
a te che non funziona, non agli altri.


Addì  martedì 1 giugno 2010 13:43 Giovanni scrisse un 
sacco di stronzate di cane.
Senti bello, tu non sapevi neanche cosa era la sostituzione 
dei processi, tu dicevi che  <( ... ) non stava nè in cielo nè 
in terra, tu ti sei scusato delle cavolate che tu hai detto, tu 
sei quello che ora, prima di postare ancora, deve studiare 
l'argomento. Io ti ho mandato un testo da studiare. Hai 
ricevuto il link?= bene, ora studia e non rompere le palle.

 ricevuto il link?= bene, ora studia e non rompere le palle.
Allora sei stronzo come gli altri.
Ho letto il tuo favoloso link (che d'altronde avevo letto anni fa) ed 
ho anche tentato gli esempi descritti nella guida avanzata.  Ma non 
funzionano!
Anche il semplice comando "cat <(ls -l)" descritto nella guida dà errore
$ lsodgf0@monica:~ > sh -x << DONE
 > cat <(ls -l)
 > DONE
sh: line 1: syntax error near unexpected token `('
sh: line 1: `cat <(ls -l)'
$ lsodgf0@monica:~ >
E prima di scrivere altre banalità prova.


 
Allora sei proprio quello che pensavo.
$ lsodgf0@monica:~ > ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Apr 21 14:25 /bin/sh -> bash*
$ lsodgf0@monica:~ > sh -x << fine
 > cat <(ls -l)
 > fine
sh: line 1: syntax error near unexpected token `('
sh: line 1: `cat <(ls -l)'
$ lsodgf0@monica:~ >
Ed ora sai dare una spiegazione?  O sai solo scrivere banalità?


 DONE
-rw-r--r--  1 sysadmin sysadmin       8289 Dec  7 11:40 
changeset_r63714.diff                                                                               
-rw-r--r--  1 sysadmin sysadmin       1555 Dec  7 11:30 
changeset_r63909.diff  


 Ed ora sai dare una spiegazione?  O sai solo scrivere banalità?
Si', so dare una spiegazione. E dovresti leggere il manuale, ogni tanto. Se 
bash viene invocata col nome "sh", opera in posix mode, e molte feature (tra 
cui, sorpresa, sorpresa, la sostituzione di processo) sono DISABILITATE. 
Vediamo se lo capisci adesso.


 E si conferma che il problema e' sh.
Non è detto. La dash, per esempio, dà effettivamente errore, ma è un
errore descritto diversamente:
lem@biggy:~$ dash -c 'cat <(ls -l)'
dash: Syntax error: "(" unexpected
Ma che succede con una bash lanciata con posix?
lem@biggy:~$ bash --posix -c 'cat <(ls -l)'
bash: -c: riga 0: errore di sintassi vicino il simbolo non atteso "("
bash: -c: riga 0: `cat <(ls -l)'
Bingo.
--
Bye, Lem

 Ma che succede con una bash lanciata con posix?
...che e' cio' che bash fa quando e' invocata con sh...


 ...che e' cio' che bash fa quando e' invocata con sh...
Che vergogna, non me lo ricordavo proprio! Grazie. :)
--
Bye, Lem

 E prima di scrivere altre banalità prova.
La sintassi <(...) è specifica di bash e non aderente a POSIX.
Quindi avevo ragione di scrivere che '<(' non ha alcun valore 
sintattico.  Se bash viene invocata come sh segue POSIX
Da man bash:
When invoked as sh, bash enters posix mode after the startup files are 
read.


 Ed ora sai dare una spiegazione?  O sai solo scrivere banalità?
La sintassi <(...) è specifica di bash e non aderente a POSIX.
Quindi avevo ragione di scrivere che '<(' non ha alcun valore 
sintattico.  Se bash viene invocata come sh segue POSIX
Da man bash:
When invoked as sh, bash enters posix mode after the startup files are 
read.
Ciao


 Vediamo se lo capisci adesso.
Ci sono arrivato leggendo le man pages.
Ma se tu le leggi ogni sera prima di dormire e le conosci tanto bene 
perché non lo hai scritto prima invece di scrivere le solite banalità 
e perdere tempo inutilmente?


 e perdere tempo inutilmente?
Perche' mi era sfuggito che stavi usando "sh" invece di "bash" (anche 
perche' il codice iniziale usava "#!/bin/bash", cosi' come tutti quelli a 
cui funzionava), me ne sono accorto solo in uno degli ultimi messaggi quando 
hai postato i comandi che stavi usando.


 Quindi avevo ragione
Come no, hai ragione e i fatti ti cosano. Ora però fuori dalle palle,
neh.
--
Bye, Lem

 palle, neh.
Ma tutti stronzi presuntuosi sul NG?
Perché non ti fai un giro su it.fan.culo
