Capitolo 28. Zero e Null

/dev/zero e /dev/null

Usi di /dev/null

Si pensi a /dev/null come a un "buco nero". Equivale, quasi, ad un file in sola scrittura. Tutto quello che vi viene scritto scompare per sempre. I tentativi per leggerne o visualizzarne il contenuto non danno alcun risultato. Ciò nonostante, /dev/null può essere piuttosto utile sia da riga di comando che negli script.

Sopprimere lo stdout.

cat $nomefile >/dev/null
# Il contenuto del file non verrà visualizzato allo stdout.

Sopprimere lo stderr (da Esempio 15-3).

rm $nomestrano 2>/dev/null
#           Così i messaggi d'errore [stderr] vengono "sotterrati".

Sopprimere gli output di entrambi, stdout e stderr.

cat $nomefile 2>/dev/null >/dev/null
#  Se "$nomefile" non esiste, come output non ci sarà alcun messaggio d'errore.
#  Se "$nomefile" esiste, il suo contenuto non verrà visualizzato allo stdout.
#  Quindi, la riga di codice precedente, in ogni caso, non dà alcun risultato.
#
#  Ciò può rivelarsi utile in situazioni in cui è necessario verificare il
#+ codice di ritorno di un comando, ma non si desidera visualizzarne l'output.
#
# cat $nomefile &>/dev/null
#     anche in questa forma, come ha sottolineato Baris Cicek.

Cancellare il contenuto di un file, preservando il file stesso ed i rispettivi permessi (da Esempio 2-1 e Esempio 2-3):

cat /dev/null > /var/log/messages
#  : > /var/log/messages   ha lo stesso effetto e non genera un nuovo processo.

cat /dev/null > /var/log/wtmp

Svuotare automaticamente un file di log (ottimo specialmente per trattare quei disgustosi "cookie" inviati dai siti di commercio sul Web):

Esempio 28-1. Evitare i cookie

if [ -f ~/.netscape/cookies ]  # Se esiste, lo cancella.
then
  rm -f ~/.netscape/cookies
fi

ln -s /dev/null ~/.netscape/cookies
#  Tutti i cookie vengono ora spediti nel buco nero, invece di essere salvati
#+ su disco.
Usi di /dev/zero

Come /dev/null, anche /dev/zero è uno pseudo file, ma in realtà genera un flusso di null (zeri binari, non del genere ASCII). Un output scritto in /dev/zero scompare, ed è abbastanza difficile leggere i null reali contenuti nel file, sebbene questo possa essere fatto con od o con un editor esadecimale. L'uso principale di /dev/zero è quello di creare un file fittizio inizializzato, di dimensione predeterminata, da usare come file di scambio (swap) temporaneo.

Esempio 28-2. Impostare un file di swap usando /dev/zero

#!/bin/bash
# Creare un file di swap.

UID_ROOT=0         # Root ha $UID 0.
E_ERR_UTENTE=65    # Non root?

FILE=/swap
DIMENSIONEBLOCCO=1024
BLOCCHIMIN=40
SUCCESSO=0


# Questo script deve essere eseguito da root.
if [ "$UID" -ne "$UID_ROOT" ]
then
  echo; echo "Devi essere root per eseguire questo script."; echo
  exit $E_ERR_UTENTE
fi


blocchi=${1:-$BLOCCHIMIN}    #  Imposta a 40 blocchi il valore predefinito, se
                             #+ non viene specificato diversamente da riga di
                             #+ comando.
# Equivale al seguente blocco di codice.
# --------------------------------------------------
# if [ -n "$1" ]
# then
#   blocchi=$1
# else
#   blocchi=$BLOCCHIMIN
# fi
# --------------------------------------------------


if [ "$blocchi" -lt $BLOCCHIMIN ]
then
  blocchi=$BLOCCHIMIN       # La dimensione deve essere di almeno 40 blocchi.
fi


######################################################################
echo "Creazione di un file di swap della dimensione di $bloccchi blocchi (KB)."
dd if=/dev/zero of=$FILE bs=$DIMENSIONEBLOCCO count=$blocchi  #  Pone il file a
                                                              #+ zero.
mkswap $FILE $blocchi             # Lo designa come file di swap.
swapon $FILE                      # Attiva il file di swap.
#  È da notate che se uno o più dei precedenti comandi dovesse fallire,
#+ questo potrebbe causare dei problemi pericolosi.
######################################################################

#  Esercizio:
#  Riscrivete il precedente blocco di codice in modo che, 
#+ in caso di fallita esecuzione, vengano eseguite le seguenti azioni:
#    1) invio di un messaggio d'errore allo stderr,
#    2) cancellazione di tutti i file temporanei, e
#    3) uscita dallo script nella modalità consueta ma con un
#+      appropriato codice d'errore.

echo "Il file di swap è stato creato ed attivato."

exit $SUCCESSO

Un'altra applicazione di /dev/zero è quella di "svuotare" un file della dimensione indicata da usare per uno scopo specifico, come montare un filesystem su un dispositivo di loopback (vedi Esempio 16-8) o per la cancellazione di "sicurezza" di un file (vedi Esempio 15-55).

Esempio 28-3. Creare un ramdisk

#!/bin/bash
# ramdisk.sh

#  Un "ramdisk" è un segmento della memoria RAM 
#+ che si comporta come se fosse un filesystem. 
#  Presenta il vantaggio di un accesso velocissimo (tempo di lettura/scrittura)
#  Svantaggi: volatilità, perdita di dati al riavvio o in caso di mancanza di
#+            corrente elettrica, meno RAM disponibile al sistema.
#
#  Cos'ha di buono un ramdisk?
#  Tenere una serie elevata di dati, come una tabella o un dizionario,
#+ su un ramdisk ne velocizza la consultazione, perché l'accesso
#+ alla memoria è molto più veloce di un accesso al disco.


E_NON_ROOT=70                  # Deve essere eseguito da root. 
NOME_ROOT=root 

MOUNTPT=/mnt/ramdisk 
DIMENSIONE=2000                # 2K blocchi (modificare in base alle esigenze)
DIMENSIONEBLOCCO=1024          # 1K (1024 byte) 
DISPOSITIVO=/dev/ram0          # Primo dispositivo ram 

nomeutente=`id -nu` 
if [ "$nomeutente" != "$NOME_ROOT" ] 
then 
  echo "Devi essere root per eseguire \"`basename $0`\"." 
  exit $E_NON_ROOT 
fi 

if [ ! -d "$MOUNTPT" ]         #  Verifica se già esiste il punto di mount,
then                           #+ in modo che non ci sia un errore se lo script
  mkdir $MOUNTPT               #+ viene eseguito più volte. 
fi 

##############################################################################
dd if=/dev/zero of=$DISPOSITIVO count=$DIMENSIONE bs=$DIMENSIONEBLOCCO 
                               #  Pone il dispositivo RAM a zero.
                               #  Perché questa operazione è necessaria?
mke2fs $DISPOSITIVO            #  Crea, su di esso, un filesystem di tipo ext2.
mount $DISPOSITIVO $MOUNTPT    #  Lo monta. 
chmod 777 $MOUNTPT             #  Abilita l'accesso al ramdisk da parte di un
                               #+ utente ordinario.
                               #  Tuttavia, si deve essere root per smontarlo.
##############################################################################
#  Occorre verificare se i precedenti comandi hanno avuto successo, 
#+ altrimenti potrebbero verificarsi dei problemi.
#  Esercizio: modificate lo script per renderlo più sicuro.

echo "\"$MOUNTPT\" ora è disponibile all'uso."
#  Il ramdisk è accessibile, per la registrazione di file, anche ad un utente
#+ ordinario.

#  Attenzione, il ramdisk è volatile e il contenuto viene perso
#+ in caso di riavvio del PC o mancanza di corrente.
#  Copiate tutto quello che volete salvare in una directory regolare.

# Dopo un riavvio, rieseguite questo script per reimpostare il ramdisk.
# Rifare il mount di /mnt/ramdisk senza gli altri passaggi è inutile.

#  Opportunamente modificato, lo script può essere invocato in
#+ /etc/rc.d/rc.local per impostare automaticamente un ramdisk in fase di boot.
#  Potrebbe essere appropriato, ad esempio, su un server database.

exit 0

In aggiunta a quanto detto sopra, /dev/zero è richiesto dai binari ELF.