Raspberry Pi root filesystem in read only

Raspberry Pi è un piccolo e simpatico dispositivo, un PC completo, con SO Linux dal costo di poche decine di euro. Ideale per imparare Linux e applicazioni varie, anche di una certa importanza, ma con le dovute premesse.

Raspberry ha come dispositivo di boot una scheda SD nella quale, normalmente, si trova anche il file system (FS) root. La scheda SD non è molto affidabile specie per il file system. Numerose operazioni di scrittura ed interruzioni di alimentazione possono portare a corruzione del FS e conseguenti problemi.

Una soluzione è usare la scheda SD solo per il boot e installare il FS su un dispositivo più affidabile come una memoria USB o un disco esterno. In alternativa si può montare il FS di root dalla scheda SD, ma solo in lettura.Qui viene descritta quest'ultima soluzione.

E' utile anche disabilitare tutti i processi che non sono utili alla applicazione implementata e che scrivono sul FS. Fra questi anche lo swap dopo aver verificato che la memoria RAM è sufficiente per i nostri scopo.

Premesso che con Raspberry non è gestito lo switch su SD per la protezione da scrittura, rimane la soluzione di montare il FS di root in sola lettura.

Per il corretto funzionamento del dispositivo occorre garantire la possibilità di scrivere su alcune directory che normalmente fanno parte del FS root, ad esempio /var/log, /tmp /home. Si può ovviare facendo montando un FS  o in ram o su una partizione diversa da root. Nella configurazione illustrata in parte si farà uso di un FS in ram, in parte di una partizione sulla stessa SD, confidando nel fatto che la corruzione di una partizione che non contiene root è meno critica e si può, con maggiore semplicità, gestire backup e ripristini.

Nell'esempio si è utilizzato una scheda SD da 32 GB, classe 10, che è stata inizializzata con Raspbian.

Al primo avvio viene eseguita la procedura di configurazione raspi-config.

Non espandere il FS ,  e configurare le varie opzioni come la password, la selezione della lingua, il nome del dispositivo e l'abilitazione di ssh.

La scheda SD da 32G la partizione di boot è di 56 MB, mentre la root è di 3GB e restano disponibili circa 26 - 27 GB. In relazione alle applicazioni che si installeranno, potrebbe essere necessario ampliare la partizione di root.

Si creano le partizioni su SD per gli usi che necessitano, in particolare per la cartella /home e /tmp. Per la prima partizione riservo 20 GB per la seconda 1 GB.

Per visualizzare le partizioni presenti: fdisk -l

root@weewx-pi:~# fdisk -l
Disk /dev/mmcblk0: 32.1 GB, 32090619904 bytes
4 heads, 16 sectors/track, 979328 cylinders, total 62676992 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0009bf4f
        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            8192      122879       57344    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          122880     6399999     3138560   83  Linux

 

Il device SD ha nome mmcblk0, mmcblkop1 e mmcblk0p2 sono le partizioni di boot e di root. Per cereare le nuove partizioni fdisk /dev/mmcblk0

fdisk /dev/mmcblk0

Command (m for help): p

Disk /dev/mmcblk0: 32.1 GB, 32090619904 bytes
4 heads, 16 sectors/track, 979328 cylinders, total 62676992 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0009bf4f
        Device Boot      Start         End      Blocks   Id  System
dev/mmcblk0p1            8192      122879       57344    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          122880     6399999     3138560   83  Linux

Command (m for help): n

Partition type:

   p   primary (2 primary, 0 extended, 2 free)
   e   extended

Select (default p): p

Partition number (1-4, default 3):
Using default value 3

First sector (2048-62676991, default 2048): 6400000
Last sector, +sectors or +size{K,M,G} (6400000-62676991, default 62676991): +20G

Command (m for help):

 

La partizione da 20 GB è la terza partizione primaria, la successiva deve essere un partizione estesa entro la quale troveranno posto le successive partizioni. Questo è il risultato finale:

Command (m for help): p

Disk /dev/mmcblk0: 32.1 GB, 32090619904 bytes
4 heads, 16 sectors/track, 979328 cylinders, total 62676992 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk identifier: 0x0009bf4f

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            8192      122879       57344    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          122880     6399999     3138560   83  Linux
/dev/mmcblk0p3         6400000    48343039    20971520   83  Linux
/dev/mmcblk0p4        48343040    62676991     7166976    5  Extended
/dev/mmcblk0p5        48345088    50442239     1048576   83  Linux

La tabella delle partizioni viene letta al boot o forzata con il comando partprobe

Creiamo i FS con il comando mke2fs.

root@weewx-pi:~# mke2fs -t ext4 -L homeFS /dev/mmcblk0p3

mke2fs 1.42.5 (29-Jul-2012)
Discarding device blocks: fatto
Etichetta del filesystem=homeFS
OS type: Linux
Dimensione blocco=4096 (log=2)
Dimensione frammento=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
1310720 inodes, 5242880 blocks
262144 blocks (5.00%) reserved for the super user
Primo blocco dati=0
Maximum filesystem blocks=0
160 gruppi di blocchi
32768 blocchi per gruppo, 32768 frammenti per gruppo
8192 inode per gruppo
Backup del superblocco salvati nei blocchi:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,    4096000

Allocating group tables: fatto
Scrittura delle tavole degli inode: fatto
Creating journal (32768 blocks): fatto
Scrittura delle informazioni dei superblocchi e dell'accounting del filesystem: fatto

root@weewx-pi:~# mke2fs -t ext4 -L tmpFS /dev/mmcblk0p5

mke2fs 1.42.5 (29-Jul-2012)
Discarding device blocks: fatto
Etichetta del filesystem=tmpFS
OS type: Linux
Dimensione blocco=4096 (log=2)
Dimensione frammento=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
65536 inodes, 262144 blocks
13107 blocks (5.00%) reserved for the super user
Primo blocco dati=0
Maximum filesystem blocks=268435456
8 gruppi di blocchi
32768 blocchi per gruppo, 32768 frammenti per gruppo
8192 inode per gruppo
Backup del superblocco salvati nei blocchi:
        32768, 98304, 163840, 229376

Allocating group tables: fatto
Scrittura delle tavole degli inode: fatto
Creating journal (8192 blocks): fatto
Scrittura delle informazioni dei superblocchi e dell'accounting del filesystem: fatto

root@weewx-pi:~#

 

La partizione home è montata provvisoriamente su /mnt per copiare il contenuto di /home

root@weewx-pi:~# mount /dev/mmcblk0p3 /mnt
root@weewx-pi:~# cd /mnt
root@weewx-pi:/mnt# cp -r /home/* .
root@weewx-pi:/mnt# ls
lost+found  pi
root@weewx-pi:/mnt#

 

In /home è presente solo /home/pi. Ora è possibile modificare il file /etc/fstab per il mount definitivo delle due partizioni.

proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    defaults          0       2
/dev/mmcblk0p2  /               ext4    defaults,noatime  0       1
/dev/mmcblk0p3  /home           ext4    defaults,noatime  0       1
/dev/mmcblk0p5  /tmp            ext4    defaults,noatime  0       1

A questo punto si può fare un reboot per vedere l'effetto che fa.

root@weewx-pi:~# reboot

Broadcast message from root@weewx-pi (pts/0) (Tue May 12 11:59:39 2015):
The system is going down for reboot NOW!

root@weewx-pi:~#

 

Dopo il reboot il comando mount mostra il risultato e le partizioni.

 root@weewx-pi:/tmp# mount

/dev/root on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=218604k,nr_inodes=54651,mode=755)
tmpfs on /run type tmpfs (rw,nosuid,noexec,relatime,size=44576k,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)

proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /run/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=89140k)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
/dev/mmcblk0p1 on /boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
/dev/mmcblk0p3 on /home type ext4 (rw,noatime,data=ordered)
/dev/mmcblk0p5 on /tmp type ext4 (rw,noatime,data=ordered)

root@weewx-pi:/tmp#

Da notare che /run /run/lock e /run/shm sono filesystem in ram (tmpfs). La gestione di questi FS è delagata al dile di configurazione /etc/default/tmpfs

Normalmente lascio la cartella lost+found, anche se praticamente inutile, giusto per evidenziare il nuovo filesystem

root@weewx-pi:/tmp# ls -al /home
totale 28
drwxr-xr-x  4 root root  4096 mag 12 11:43 .
drwxr-xr-x 22 root root  4096 feb 15 12:27 ..
drwx------  2 root root 16384 mag 12 11:38 lost+found
drwxr-xr-x  3 root root  4096 mag 12 11:43 pi

root@weewx-pi:/tmp#

 

A questo punto è conveniente aggiornare il software e il firmware.

sudo apt-get update
sudo apt-get upgrade
apt-get clean

Per disabiltare lo swap:

swapoff --all

Lo swap in Raspberry è gestiti non con una propria partizione, ma attraverso il processo dphys-swapfile che crea l'aera di swap in /var/swap. Occorre anche evitare che la gestion dello swap parta al boot disabilitando la il relativo servizio o disinstallando  pdhys-svapfile.

update-rc.d dphys-swapfile disable

Resta da spostare la cartella /var/log un filesystem in ram modificando il file /etc/fstab. Al riavvio di verranno persi i file di log, ma in diversi casi è cosa accettabile.

proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    defaults          0       2
/dev/mmcblk0p2  /               ext4    defaults,noatime  0       1
/dev/mmcblk0p3  /home           ext4    defaults,noatime  0       1
/dev/mmcblk0p5  /tmp            ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, so no using swapon|off from here on, use  dphys-swapfile swap[on|off]  for that
none            /var/log        tmpfs   size=2M,noatime

L'ultima riga crea un filesystem in ram di 2 MB.

per montare il nuovo FS:

mount -a

Altri file da spostare in una area scrivibile sono quelli relativi alla gestione di dhcp, oppure occorre definire un indirizzi IP statico. Sposto questi file in /tmp con un link simbolico.

root@weewx-pi:~# rm -rf /var/lib/dhcp/
root@weewx-pi:~# ln -s /tmp /var/lib/dhcp
root@weewx-pi:~#
root@weewx-pi:~# cp /etc/resolv.conf /tmp/resolv.conf
root@weewx-pi:~# rm /etc/resolv.conf
root@weewx-pi:~# ln -s /tmp/resolv.conf /etc/resolv.conf
root@weewx-pi:~#

Non resta che abilitare read only (ro) per il FS di root in /etc/fstab

/dev/mmcblk0p2  /            ext4    ro,defaults,noatime  0       1

e fare il reboot

Nel riavvio porre attenzione al log per eventuali errori.

A questo punto non è più possibile modificare file nella partizione di root. All'occorrenza bisogna riabilitare la scrittura, modificare eventuali configurazioni e riabilitare la sola lettura.

Per ripristinare la scrittura:

mount  -o remount rw /

Tipologia: 

Commenti

Ringrazio per l'ottima guida per mettere in read-only la SD; prima di metterla in pratica chiedo solo un parere tecnico: ho visto che altri risolvono il problema utilizzando tmpfs per scrivere temporaneamente su RAM; quali sono i pro e i contro?

 

Un filesystem temporaneo va bene per memorizzare dati che possono andare persi, ad esempio /tmp o /run in quanto viene distrutto quando la macchina si spegne.
Per risolvere problemi di corruzione della scheda SD, ritengo più conveniete trasferire i file system su una chiavetta USB. Meglio ancora un disco, magari allo ststo solido. Troppo lusso. smiley