Le miniguide di UbaWeb

Bash: log, decimali, arrotondamento,

Premessa Torna su

19 agosto 2012 - Linux 2.6.32-42-generic-pae -Ubuntu i686 GNU/Linux - Come ben saprete ogni tanto è bene dare una pulita a "/var/log/" cancellando i file vecchi.
Da tempo uso un piccolo script che mi ero fatto qualche mese fa, ora volevo migliorarlo in modo che venisse mostrato lo spazio recuperato (in bytes, Kb e Mb) dopo la cancellazione dei vecchi file di log. Sembrava una modifica semplice, invece mi sono scontrato con lo strano comportamento di printf che ho usato per l'arrotondamento che ora vado a descrivere.

Il problema dei numeri con decimaliTorna su

Con bash si possono fare calcoli matematici solo tra numeri interi, per operazioni con numeri decimali si devono usare strumenti esterni come bc, awk o altri linguaggi. Per l'arrotondamento ho deciso di ricorrere a printf perché bc non arrotonda ma tronca i decimali al decimale indicatogli.
Facendo qualche prova mi sono accorto che secondo come viene usato, printf, vuole che il numero sia passato con la , (virgola), come separatore di decimali, mentre in altri casi con il . (punto)
Per vedere questo comportamento basta provare ad eseguire questo codice:

numero_virgola=4,5599999 con_virgola=$( printf "%.2f\n" $numero_virgola ) echo "con virgola: $con_virgola " #stdout-> 4,56 ## ok ## numero_punto=4.559999 con_punto=$(printf "%.2f\n" $numero_punto) # stdout-> printf: 4.559999: numero non valido ## errore ##

Con AWK

numero_punto=4.559999 arrotondatot=$(echo $numero_punto | awk '{printf("%.2f\n", $1)}') #arrotondo a 2 cifre echo $arrotondato # stdout-> 4,56 ## ok ## numero_virgola=4,559999 arrotondato=$(echo $numero_virgola | awk '{printf("%.2f\n", $1)}') #arrotondo a 2 cifre echo $arrotondato # stdout-> 4.00 ## ???? ##

Quindi nello script sono stato obbligato ad usare questo codice (du stampa come separatore il punto):

prima_b=$(du -sb) # calcolo (-s:totale) dello spazio occupato (-b:in bytes) prima_b=$(echo $prima_b | grep -o '[0-9]*') # PULIZIA, prendo solo i numeri prima_kb=$(echo "$prima_b / 1024" | bc -l) # calcolo kb con decimali prima_kb_arr=$(echo $prima_kb | awk '{printf("%.2f\n", $1)}') # arrotondo a 2 cifre prima_mb=$(echo "$prima_kb / 1024" | bc -l) # calcolo mb con decimali prima_mb_arr=$(echo $prima_mb | awk '{printf("%.2f\n", $1)}') # arrotondo a 2 cifre echo -e "Lo spazio totale occupato dai log è: in bytes\t$prima_b in Kbytes\t$prima_kb_arr in Mbytes\t$prima_mb_arr"

(Ora guardo il motogp, poi inserisco le classifiche e poi continuo... a chi interessa, da qualche anno, ho fatto una pagina con: classifica, calendario, griglie e i risultati del motogp per gli anni 2010, 2011, 2012 all'indirizzo: http://www.ubaweb.it/motogp/).

Ho scritto anche un post sul forum di Ubuntu per avere qualche delucidazione sulla questione, quando avrò risposta aggiornerò questa pagina.

Lo script per cancellare i file di logTorna su

Questo script non cancella tutti i file di log ma solo quelli di backup, tutti i file recenti (che non hanno backup) non vengono toccati.
I file che vengono cancellati nella directory "/var/log/" e sue sottodirectory, sono quelli con estensione: .gz, .1, .old.
Nella sua esecuzione mostra lo spazio occupato dai file: prima della cancellazione, dopo la cancellazione e lo spazio recuperato; tutti i valori sono mostrati in bytes, kilobites e megabytes.
Conviene mettere lo script in una directory presente nel PATH (es.: /usr/local/bin) per poterlo eseguire da qualsiasi posizione del filesystem; per farlo: sudo mv percorso/dello/script/canc_log.sh /usr/local/bin/; naturalmente va reso eseguibile.
Deve essere eseguito da root, quindi, con: sudo canc_log.sh.
Il codice è ipercommentato e facilmente modificabile per adattarlo ad altre esigenze; per esempio, per cambiare la directory su cui deve intervenire, basta cambiare il valore della variabile DIR_LOG ad inizio script.
Buon Linux a tutti 9-)
Mi dimenticavo di mettere il link per il download dello script, che è canc_log.sh
Ciao ciao 9-)

Una mezza soluzioneTorna su

20 agosto 2012 - Come ho scritto sul forum:
"
Altra stranezza ma che può essere utile; utilizzando il percorso dell'eseguibile printf al posto di "printf" non ho più l'errore e il numero che inizialmente aveva il punto viene restituito con la virgola.

prtf=$(which printf) # /usr/bin/printf numero_punto=4.559999 con_punto=$($prtf "%.2f\n" $numero_punto) echo $con_punto # stdout-> 4,56 ## risultato corretto ma punto convertito in virgola ## prtf=$(which printf) # /usr/bin/printf numero_virgola=4,559999 con_virgola=$($prtf "%.2f\n" $numero_punto) echo $con_virgola # stdout-> 4,56 ## ok ##

"

crap0101 scrive:
"
Per avere un comportamento meno disorientante potresti decidere, nello script, il formato in cui trattare questi valori, settando il locale o alcune delle varialibi relative (LANG, LC_NUMERIC; LC_MONETARY, ecc), ad esempio:

echo $LANG # stdout->it_IT.UTF-8 prtf=$(which printf) # /usr/bin/printf numero_punto=4.559999 con_punto=$($prtf "%.2f\n" $numero_punto) echo $con_punto # stdout->4,56 LANG=C con_punto=$($prtf "%.2f\n" $numero_punto) echo $con_punto # stdout->4.56

"

Ultime...si tratta di un bug

23 agosto 2012 - Ho provato a guardarmi le pagine man per veder se le mie impostazioni di localizzazione fossero corrette fino a quando guardando la pagina man di "localeconv" ...:

man localeconv ... DESCRIPTION: The localeconv() function returns a pointer to a struct lconv for the current locale. This structure is shown in locale(7), and contains all values associated with the locale categories LC_NUMERIC and LC_MONETARY. Programs may also use the functions printf(3) and strfmon(3), which behave according to the actual locale in use. ... BUGS: The printf(3) family of functions may or may not honor the current locale. ...

)-8 Perché non hanno messo la voce BUG nel man di printf? 8-(

Vedere quanto scritto all'indirizzo: http://forum.ubuntu-it.org/viewtopic.php?f=33&t=532557 del forum di Ubuntu.

Torna su
Sito realizzato da: UbaWeb di Giovanni Ubaldi

Licenza Creative Commons Tutto il contenuto di questo sito se non diversamente dichiarato è di Giovanni Ubaldi ed è distribuito con Licenza:

Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale.