概要
-
raspberry pi overlayfs
とかで、検索していたら、Domoticz - Open Source Home Automation SystemというプロジェクトのWikiに気になる記事が。 -
Setting up overlayFS on Raspberry Pi
-
/boot
とroot
ファイルシステムは通常、読み取り専用(ro)ーに変更. -
/var
と/home
は読み書きできる(rw)オーバーレイファイルシステムに変更. -
/etc/init.d/saveoverlays
のinitスクリプトで、システムのシャットダウンと再起動時にSDに同期させる。
-
これを使用すると、ほぼ完全にSDカードの書き込みを排除することができます。 読み書きの部分は、RAMベース(=Ramdisk)なので、(Domoticzを)スピードアップします。
#1 Google翻訳+ちょいと改
#2 Domoticz: Open Source Home Automation System というのが気になる。。がまたの機会に..
#3 再起動前にsudo service saveoverlays sync
をするのがよいかも。(RAMDisk上のファイルをSD側へ、rsync(なければコピー)してくれる)
#4 rootfsをro
にすると、apt-get
やら、できなくなる。設定の済んだ、組み込み以外は、あつかいが大変カモ?
環境
- Raspberry Pi 2/3 (1でもZeroでもいけるかと)
2016-05-27-raspbian-jessie-lite.img
手順
- 書いてあるとおりに..
- いつもの+設定など行う (
/home
と/var
しか、書き込みできなくなるので、そのようにする) -
こぴぺ
cd /tmp wget http://hansrune.net/domo/mount_overlay wget http://hansrune.net/domo/saveoverlays chmod a+rx saveoverlays mount_overlay sudo cp mount_overlay /usr/local/bin sudo cp saveoverlays /etc/init.d/ # # # Swapをとめる. sudo dphys-swapfile swapoff sudo dphys-swapfile uninstall sudo update-rc.d dphys-swapfile disable # # # fake-hwclockサービスは、`/etc/fake-hwclock.data`ファイルを読み書きするので、実態を/var以下に移して、リンクをはる. # ここでサービスをdisableするが、saveoverlaysサービスで、呼ばれる sudo service fake-hwclock stop sudo mv /etc/fake-hwclock.data /var/log/fake-hwclock.data sudo ln -s /var/log/fake-hwclock.data /etc/fake-hwclock.data sudo service fake-hwclock start sudo update-rc.d fake-hwclock disable # # インストール fuse lsof rsync # lsof: ファイルシステムをリードオンリーに再マウントできないとき、オープンしてるファイルをみつけるのに役立つよ. sudo apt-get install -y fuse lsof rsync # # roを開始するとめんどうになるので、いろんな設定をしといたほうがいいかと。 # # # #サービス開始 sudo systemctl enable saveoverlays.service
-
sudo vi /boot/cmdline.txt
/boot/cmdline.txtdwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait noswap fastboot ro
-
noswap fastboot ro
を追加
-
-
sudo vi /etc/fstab
/etc/fstabproc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat ro 0 2 /dev/mmcblk0p2 / ext4 ro,noatime 0 1 mount_overlay /var fuse nofail,defaults 0 0 mount_overlay /home fuse nofail,defaults 0 0 none /tmp tmpfs defaults 0 0
-
/dev/mmcblk0p1
と/dev/mmcblk0p2
がro
になってるよ
-
-
Overlay関連
こぴぺ# #Overlayに使うのディレクトリ sudo mv /home /home_org sudo mkdir /home /home_rw sudo mv /var /var_org sudo mkdir /var /var_rw # #マウントしてみて、確認. sudo mount /home sudo mount /var # mount | grep home ; mount | grep var ls -la /home/pi
こんなかんじpi@raspberrypi:~ $ mount | grep home ; mount | grep var ramdisk on /home_rw type tmpfs (rw,relatime) overlay on /home type overlay (rw,relatime,lowerdir=/home_org,upperdir=/home_rw/upper,workdir=/home_rw/work) ramdisk on /var_rw type tmpfs (rw,relatime) overlay on /var type overlay (rw,relatime,lowerdir=/var_org,upperdir=/var_rw/upper,workdir=/var_rw/work) pi@raspberrypi:~ $ ls -la /home/pi total 20 drwxr-xr-x 2 pi pi 4096 Jun 14 23:03 . drwxr-xr-x 1 root root 40 Jun 14 23:28 .. -rw-r--r-- 1 pi pi 220 May 27 11:09 .bash_logout -rw-r--r-- 1 pi pi 3512 May 27 11:09 .bashrc -rw-r--r-- 1 pi pi 675 May 27 11:09 .profile -rw------- 1 pi pi 57 Jun 14 23:03 .Xauthority
sudo reboot
-
マウントできてるか確認
mountpi@raspberrypi:~ $ mount /dev/mmcblk0p2 on / type ext4 (ro,noatime,data=ordered) . . . fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime) none on /tmp type tmpfs (rw,relatime) ramdisk on /home_rw type tmpfs (rw,relatime) ramdisk on /var_rw type tmpfs (rw,relatime) /dev/mmcblk0p1 on /boot type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro) overlay on /var type overlay (rw,relatime,lowerdir=/var_org,upperdir=/var_rw/upper,workdir=/var_rw/work) overlay on /home type overlay (rw,relatime,lowerdir=/home_org,upperdir=/home_rw/upper,workdir=/home_rw/work) pi@raspberrypi:~ $
- 見所
/dev/mmcblk0p2 ... (ro, ...)
: リードオンリー/dev/mmcblk0p1 ... (ro, ...)
: リードオンリー/home_rw
と/var_rw
: RAMディスク/home
と/var
: lowerdirをベースにupperdirを重ねる(lowerdir=/XXX_org,upperdir=/XXX_rw/upper,workdir=/XXX_rw/work
で、overlay)
- 見所
システムメンテナンスのためのスクリプト
-
systemd
を使っているとうまく動かないので、↓のコメントの変更したスクリプトを使用すること!
sysmaint.shというファイル名にしときます.
#!/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 {home,var}; do mount --rbind /${f}_org /chroot/$f; done
# bind remaining directories
for f in {bin,boot,etc,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 /
sudo ./sysmaint.sh
-
=> 実行すると
chroot
つかって、ファイルの読み書きができるようになる(#/etc/fstab
で、rwにして再起動とか..)例pi@raspberrypi:~$ sudo ./sysmaint.sh Note: /boot is still mounted read-only, remount to read-write if needed. You are now in read-write chroot. Use CTRL+D when done to exit chroot and mount read-only again. (rw) root@raspberrypi:/$ vi /etc/fstab ... (rw) root@raspberrypi:/$ logout Chroot left, re-mounting read-only again. pi@raspberrypi:~$
もし、読み取り専用に再マウントできなかったら
sudo service saveoverlays sync
sudo reboot
SDカードにシンクできてるかな?
/var/log/saveoverlays.log
にログってる。
その他
mount_overlay
hansrune.net/domo/mount_overlay
#!/bin/sh
DIR="$1"
[ -z "${DIR}" ] && exit 1
#if ! grep -q overlay /proc/filesystems
#then
# echo "Filesystem overlay is not available. You need a kernel update: apt-get update && apt-get upgrade" >&2
# exit 2
#fi
if [ ! -d "${DIR}_org" ]
then
echo "${DIR}_org does not exist" >&2
exit 1
fi
if [ ! -d "${DIR}_rw" ]
then
echo "${DIR}_rw does not exist" >&2
exit 1
fi
#
# ro must be the first mount option for root .....
#
ROOT_MOUNT=$( grep -v "^#" /etc/fstab | awk '$2=="/" { print substr($4,1,2) }' )
if [ "$ROOT_MOUNT" != "ro" ]; then
/bin/mount --bind ${DIR}_org ${DIR}
else
/bin/mount -t tmpfs ramdisk ${DIR}_rw
/bin/mkdir ${DIR}_rw/upper
/bin/mkdir ${DIR}_rw/work
OPTS="-o lowerdir=${DIR}_org,upperdir=${DIR}_rw/upper,workdir=${DIR}_rw/work"
/bin/mount -t overlay ${OPTS} overlay ${DIR}
fi
saveoverlays
hansrune.net/domo/saveoverlays
#! /bin/sh
### BEGIN INIT INFO
# Provides: saveoverlays
# Required-Start: $local_fs $time
# Required-Stop: $local_fs $syslog $time
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Save logs and files from overlay mounts
# Description: Save logs and files from overlay mounts
### END INIT INFO
# Do NOT "set -e"
#
# Testing hints:
# sudo mount -o remount,ro /
# sudo env INIT_VERBOSE=yes /etc/init.d/saveoverlays stop
# cat /var/log/saveoverlays.log
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
DESC="overlay filesystem sync"
NAME=saveoverlays
if [ -f "/etc/default/$NAME" ]; then
. "/etc/default/$NAME"
fi
TMPLOG=/tmp/$NAME.log
LOGFILE=/var_org/log/$NAME.log
SYNCDIRS=${SYNCDIRS:-$( mount | awk '/^overlay/ { print $3 ":" $3 "_org" }' )}
SYNCEXCLUDES=${SYNCEXCLUDES:-'--exclude .unionfs* --exclude .fuse_hidden* --exclude *.leases --exclude stats'}
SYNCFLAGS=${SYNCFLAGS:-"-avH --inplace --delete"}
# Check if we are running with read-only root
ROROOT=$( mount | egrep '^/dev/.*on / .*ro,' )
DOSYNC=${FORCESYNC:-"$ROROOT"}
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
if [ -n "${ROROOT}" ]
then
log_action_msg "Read-only root active"
else
log_action_msg "Read-only root inactive"
fi
if date '+%Y' | grep -q 1970
then
log_action_msg "Clock is not set. Trying fake-hwclock"
fake-hwclock load
fi
}
#
# Function that syncs the files
#
do_sync()
{
RETVAL=0
#
# If we run with overlayfs, try to sync the dirs
#
if [ -z "${ROROOT}" ] || mount -o remount,rw / >> ${TMPLOG} 2>&1
then
echo "----------------------------" >> ${TMPLOG}
echo "$NAME sync started at `date`" >> ${TMPLOG}
for DIR in ${SYNCDIRS}
do
SOURCE="${DIR%%:*}"
DEST="${DIR##*:}"
log_action_msg "Syncing ${SOURCE} to ${DEST} ..."
echo "----" >> ${TMPLOG}
echo "$NAME sync ${SOURCE} to ${DEST} with options ${SYNCFLAGS} ${SYNCEXCLUDES} at `date`" >> ${TMPLOG}
if [ -d "${SOURCE}" -a -d "${DEST}" ]
then
rsync ${SYNCFLAGS} ${SYNCEXCLUDES} ${SOURCE}/ ${DEST}/ >> ${TMPLOG} 2>&1
elif [ -f "${SOURCE}" ]
then
cp -vp ${SOURCE} ${DEST} >> ${TMPLOG} 2>&1
else
log_action_msg "Skipping this step: ${SOURCE} or ${DEST} not available"
fi
done
cat ${TMPLOG} >> ${LOGFILE}
if [ -w /etc/fake-hwclock.data ]
then
log_action_msg "Saving fake-hwclock"
fake-hwclock save
fi
log_action_msg "Sync changes to disk"
sync; sync; sync
#
# return to read-only only if that is where we started
#
if [ -n "${ROROOT}" ]
then
log_action_msg "Remount read-only"
mount -o remount,ro /
fi
else
log_action_msg "Remounting root as writeable failed!"
RETVAL=2
fi
return "$RETVAL"
}
#
# Function that stops the daemon/service
#
do_stop()
{
#
# If we run with overlayfs, try to sync the dirs
#
if [ -n "${DOSYNC}" ]
then
do_sync;
return $?
else
log_action_msg "Root is not read-only. No action"
return 0
fi
}
case "$1" in
start)
log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) log_end_msg 0 ;;
2) log_end_msg 1 ;;
esac
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) log_end_msg 0 ;;
2) log_end_msg 1 ;;
esac
;;
sync)
log_daemon_msg "Syncing $DESC" "$NAME"
do_sync
case "$?" in
0|1) log_end_msg 0 ;;
2) log_end_msg 1 ;;
esac
;;
status)
;;
restart)
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
exit 3
;;
esac
: