Raspberry Pi (の4) [プログラム]
fsprotectの代わりにunionfs-fuseを使えるようにしてみます。
unionfs-fuseはバイナリパッケージがありましたので、インストールしてみます。
# apt-get install unionfs-fuse
でも、設定がさっぱり、というか、実際に使えるようにするスクリプトがありません。たしかに、unionfs-toolsパッケージは「unionfs」をインストールするものであって、fsprotectのように(root)fsを守るものじゃないですからね。自分でなんとかしましょう。幸い、/usr/share/doc/unionfs-tools/examples/S01a-unionfs-fuse-live-cd.shがあります。使えそうな感じです。いきなり、コピーしてみました。
# cp -a /usr/share/doc/unionfs-tools/examples/S01a-unionfs-fuse-live-cd.sh /etc/rcS.d/
# reboot
動きません。init.d(rc?.d)の設定の仕方が変わっている? 昔のように単純にrc?.dを読んで実行するのではないのでしょうか?
# mv /etc/rcS.d/S01a-unionfs-fuse-live-cd.sh /etc/init.d/a-unionfs-fuse-live-cd.sh
# update-rc.d a-unionfs-fuse-live-cd defaults
エラーになります。他のスクリプトと同じように、
### BEGIN INIT INFO
# …
### END INIT INFO
が必要なようです。最初に起動するようにしてもダメです。どこにいれたら動くのか、探してみると、どうやら動きそうなのは、rootfsなどをマウントした後のようです。他のスクリプト参考にして、下記のようにしました。
### BEGIN INIT INFO
# Provides: a-unionfs-fuse-live-cd
# Required-Start: mountall-bootclean
# Required-Stop:
# Default-Start: S
# Default-Stop:
# X-Start-Before: procps udev-mtab urandom
# Short-Description: for a-unionfs-fuse-live-cd
# Description: like fsprotect
### END INIT INFO
これをrcS.dで動くようにするには、
# update-rc.d a-unionfs-fuse-live-cd defaults
です。再起動します。
これでも動きがまだおかしいです。調べてみると、当たり前ですが、a-unionfs-fuse-live-cd.shを実行する前にマウントしたdevfsなどがchrootしたせいで見えなくなっていました。
これ以上、起動する順番を探すのも面倒なので、bindマウントしてしまいましょう。
OLDROOT="$CHROOT_PATH/root"
for d in dev run run/lock sys run/shm dev/pts boot
do
mount --bind $OLDROOT/$d /$d
done
をa-unionfs-fuse-live-cd.shのpivot_rootの後ろに追加します。これで、動き始めました。
unionfsを使うと、どこを書き換えているのかが分かります。なるほど。で、/var/log/が増えてきます。syslogを止めますか。すぐ元に戻せるように、名前を変更しておきます。
# mv /etc/init.d/rsyslogd /etc/init.d/rsyslogd.origでは再起動… あれ、再起動しません。停止中に止まってしまいますよ? あ、unionfsがkillされてしまうからですね。rootfsが見えなくなっちゃう。そういえば、examplesのフォルダに、もひとつスクリプトがあったっけ。unionfs-fuse-omit-pid.shをコピー。最近は、/var/run/sendsigs.omit.d/にpidファイルを書いておくと、停止時にkillを送らないようになっているようです。へー。
a-unionfs-fuse-live-cd.shと別々に起動するのも面倒なので、a-unionfs-fuse-live-cd.sh内で呼び出しちゃいましょう。/etc/init.d/unionfs-fuse-omit-pid.shの実行を追加します。
/etc/init.d/unionfs-fuse-omit-pid.shさぁ、これでどうだ。再起動します。起動したら、再起動します。あ、動きますね。
一応、これで、fsprotectの代わりができました。
なお、Raspberry Piでは、起動時にカーネルパラメータをどうやって渡すとか修正するかとかが、わからないので、常にfsprotect状態で起動します。したがって、元のrootfsを修正するのは、mountの-o remount,rwを使って、読み書きできるようにリマウントしてから、修正することになります。
# mount -o rw,remount /dev/root /oldroot/tmp/unionfs/root一応、動くことが確認できたので、少し修正します。
# cd /oldroot/tmp/unionfs/root #ここが元の/
ます、/tmpの下にいろいろ作るよりは、fsprotectのように/の下においたほうがよいかもしれません。/unionfsに置くようにしてみましょう。また、元のrootfsと/boot(SDカードの第一パーティション)もread onlyにします。
そのような修正をしたのが、次のa-unionfs-fuse-live-cd.shになります。
/etc/init.d/a-unionfs-fuse-live-cd.sh
#!/bin/sh
### BEGIN INIT INFO
# Provides: a-unionfs-fuse-live-cd
# Required-Start: mountall-bootclean
# Required-Stop:
# Default-Start: S
# Default-Stop:
# X-Start-Before: procps udev-mtab urandom
# Short-Description: for a-unionfs-fuse-live-cd
# Description: like fsprotect
### END INIT INFO
# Copyright: Bernd Schubert <bernd.schubert@fastmail.fm>
# BSD license, see LICENSE file for details
#
# modified by hanposaki MMXIII
FUSE_OPT="-o allow_other,use_ino,suid,dev,nonempty"
UNIONFS_DIR="/unionfs"
CHROOT_PATH="$UNIONFS_DIR/unionfs"
UNION_OPT="-ocow,chroot=$CHROOT_PATH,max_files=32768"
UBIN=/usr/bin/unionfs-fuse
mount -o remount,ro /dev/mmcblk0p1 /boot
mount -t proc proc /proc
mount -t tmpfs tmpfs $UNIONFS_DIR
mkdir -p $CHROOT_PATH/root
mkdir -p $CHROOT_PATH/rw
mkdir -p $UNIONFS_DIR/union
mount --bind / $CHROOT_PATH/root
$UBIN $FUSE_OPT $UNION_OPT /rw=RW:/root=RO $UNIONFS_DIR/union
mount -t proc proc $UNIONFS_DIR/union/proc
cd $UNIONFS_DIR/union
mkdir oldroot
pivot_root . oldroot
mount -o remount,ro /dev/root /oldroot
OLDROOT="$CHROOT_PATH/root"
for d in dev run run/lock sys run/shm dev/pts boot
do
mount --bind $OLDROOT/$d /$d
done
#echo "" >/fastboot
init q
/etc/init.d/a-unionfs-fuse-omit-pid.sh
exit 0
あとは、
# update-rc.d a-unionfs-fuse-omit-pid.sh defaultsうまく動かなかったら、適当なlinuxで、SDカードのrootfsをマウントして修正しましょう。たとえば、SDカードがsdcだとすれば、
# reboot
linux# fsck -t ext4 /dev/sdc2とか。a-unionfs-fuse-omit-pid.shを止めるには、
linux# mount -t ext4 -o noatime /dev/sdc2 /mnt
linux# mv /mnt/etc/init.d/a-unionfs-fuse-omit-pid.sh /mnt/etc/init.d/a-unionfs-fuse-omit-pid.sh.stopして、Raspberry Piで再起動します。
linux# umount /mnt
うまく動くようなら、SDカードのプロテクトスイッチをロックにして、立ち上げてみます。問題となるようなエラーが起こらなければ、OKです。