Raspberry Pi. Делаем Raspbian Read-Only

Файловая система Raspberry Pi, которая устанавливается на (micro)SD-карту, как и любая файловая система на любом компьютере, может быть повреждена при незапланированном отключении питания. Как только вы сделаете файловую систему Read-Only (т.е. все изменения будут записываться не на диск, а в ОЗУ), вы сможете не бояться того, что при внезапном отключении питания или его постоянном передергивании ваша файловая система «упадет».

Как бонус, можно сделать так, что все логи, которые стандартно пишет Raspbian в /var/log будут писаться на раздел, смонтированный в ОЗУ и очищаться при перезагрузке/выключении.

Исходная точка:

  1. Raspberry Pi — версия не важна;
  2. Raspbian GNU/Linux 7 (wheezy);
  3. Подключение к интернету.

Данная статья является переводом и адаптацией Make Raspbian System Read-Only. За скрипт перевода файловой система в Read-Write спасибо k3a!

Шаг 1. Отключаем swap

Шаг 2. Устанавливаем UnionFS

UnionFS — это вспомогательная файловая система для Linux и FreeBSD, производящая каскадно-объединенное монтирование других файловых систем, часто использующаяся для монтирования разделов в ОЗУ, например, в случаях с Live CD.

$ sudo aptitude install unionfs-fuse

Шаг 3. Создаем скрипт для монтирования

Создадим файл

$ sudo nano /usr/local/bin/mount_unionfs

и добавим туда следующий контент:

!#/bin/sh
DIR=$1
ROOT_MOUNT=$(awk '$2=="/" {print substr($4,1,2)}' < /etc/fstab)
if [ $ROOT_MOUNT = "rw" ]
then
  /bin/mount --bind ${DIR}_org ${DIR}
else
  /bin/mount -t tmpfs ramdisk ${DIR}_rw
  /usr/bin/unionfs-fuse -o cow,allow_other,suid,dev,nonempty ${DIR}_rw=RW:${DIR}_org=RO ${DIR}
fi

Сделаем данный скрипт исполняемым:

$ sudo chmod +x /usr/local/bin/mount_unionfs

Шаг 4. Редактируем fstab

Откроем /etc/fstab для редактирования:

$ sudo nano /etc/fstab

И модифицируем / и /boot — заменим defaults на ro. В итоге fstab будет выглядеть следующим образом:

proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    ro                0       2
/dev/mmcblk0p2  /               ext4    ro,noatime        0       1
mount_unionfs   /etc            fuse    defaults          0       0
mount_unionfs   /var            fuse    defaults          0       0
none            /tmp            tmpfs   defaults          0       0

Шаг 5. Подготавливаем каталоги

$ sudo cp -al /etc /etc_org
$ sudo mv /var /var_org
$ sudo mkdir /etc_rw
$ sudo mkdir /var /var_rw

После выполнения данных операций, перезагружаемся:

$ sudo reboot -n

Шаг 6. Ваша файловая система уже Read-Only

Вы можете убедится в этом, посмотрев вывод команды mount:

$ mount
/dev/root on / type ext4 (ro,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=215824k,nr_inodes=53956,mode=755)
tmpfs on /run type tmpfs (rw,nosuid,noexec,relatime,size=44820k,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=89620k)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
/dev/mmcblk0p1 on /boot type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
ramdisk on /etc_rw type tmpfs (rw,relatime)
unionfs-fuse on /etc type fuse.unionfs-fuse (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other)
fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime)
ramdisk on /var_rw type tmpfs (rw,relatime)
unionfs-fuse on /var type fuse.unionfs-fuse (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other)
none on /tmp type tmpfs (rw,relatime)

Обратите внимание на следующие строки, которые говорят о том, что корневой раздел и /boot переведены в Read-Only, а UnionFS активен:

/dev/root on / type ext4 (ro,noatime,data=ordered)
...
/dev/mmcblk0p1 on /boot type vfat (ro, ...
...
unionfs-fuse on /etc ...
...
unionfs-fuse on /var ...

Перемонтирование разделов в Read-Write для обновления и внесения изменений

Может случиться так, что после перевода файловой системы в Read-Only вам потребуется внести какие-либо изменения (например, поправить настройки в /etc, обновить дистрибутив, установить новые пакеты и т.д.). Это можно сделать с помощью представленного ниже скрипта. Создайте его в любом удобном месте и дайте права на выполнение (chmod +x)

#!/bin/bash

# remount root rw
mount -o remount,rw /

# prapare target paths
mkdir -p /chroot
mkdir -p /chroot/{bin,boot,dev,etc,home,lib,opt,proc,root,run,sbin,sys,tmp,usr,var}

# mount special filesystems
mount -t proc proc /chroot/proc
mount --rbind /sys /chroot/sys
mount --rbind /dev /chroot/dev

# bind rw directories
for f in {etc,var}; do mount --rbind /${f}_org /chroot/$f; done

# bind remaining directories
for f in {bin,boot,home,lib,opt,root,run,sbin,tmp,usr}; do mount --rbind /$f /chroot/$f; done

# chroot
echo "Note: /boot is still mounted read-only, remount to read-write if needed."
echo -e "\e[33mYou are now in read-write chroot. Use CTRL+D when done to exit chroot and mount read-only again.\e[39m"
chroot /chroot /usr/bin/env PS1="(rw) \u@\h:\w\$ " /bin/bash --noprofile -l

# unmount mounts
for f in /chroot/{bin,boot,dev,etc,home,lib,opt,proc,root,run,sbin,sys,tmp,usr,var}; do
  umount -l $f
done

sleep 1

# remount read-only again
echo -e "\e[32mChroot left, re-mounting read-only again.\e[39m"
mount -o remount,ro /

Что делать, если я забыл удалить логи, а место они занимают много?

Опять же, поможет скрипт, представленный выше. После перемонтирования файловой системы в Read-Write, выполните следующие команды:

$ sudo for f in $(find . -name \*log); do > $f; done
$ cd /var_org/log
$ sudo rm -f *.gz

Резюме

Как итог, теперь ваша файловая система более надежно защищена от непредвиденных обстоятельств. Но только этого недостаточно для создания встраиваемого решения на основе Raspberry Pi — нужен еще Watchdog и система управления процессами.

Полезные ссылки

  1. Make Raspbian System Read-Only
  2. How to make Rapberry Pi truly read-only, reliable and trouble-free
  3. How to make Raspbian read-only?
  4. Debian ReadonlyRoot
  5. UnionFS на Википедии

Добавить комментарий