SSブログ

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
# reboot
うまく動かなかったら、適当なlinuxで、SDカードのrootfsをマウントして修正しましょう。たとえば、SDカードがsdcだとすれば、
linux# fsck -t ext4 /dev/sdc2
linux# mount -t ext4 -o noatime /dev/sdc2 /mnt
とか。a-unionfs-fuse-omit-pid.shを止めるには、
linux# mv /mnt/etc/init.d/a-unionfs-fuse-omit-pid.sh /mnt/etc/init.d/a-unionfs-fuse-omit-pid.sh.stop
linux# umount /mnt
して、Raspberry Piで再起動します。

うまく動くようなら、SDカードのプロテクトスイッチをロックにして、立ち上げてみます。問題となるようなエラーが起こらなければ、OKです。


共通テーマ:パソコン・インターネット

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。