ラズパイ:シャットダウンフリー tmpfs-bind編

もし、手の届かない離島に電源ブチ切りラズパイを置くなら、私ならばoverlayもfuseも使わない。理由は、デバイス屋/組込屋としての直感から来る警告だが、ここ に現実に沿ったコメントもある。
以下に紹介する方法は、X-Windowの利用が不要もしくは削除されているようなラズパイを、長期安定運用する場合などに適する。一方で、手に届く範囲の運用や趣味レベルならば、overlayfs方式を推奨する。overlayfs方式の方が起動は少し速い。なお、いずれも、ご利用は自己責任で。

前提1:tmpfsにコピーする領域は500MB未満で、なるべく小さくすること。そうできない場合には、overlayfs方式でとなる。
前提2:準備①〜③が完了していること。fuseとoverlayは不要。

~# mkdir /tmpfsroot
~# dosfslabel /dev/mmcblk0p1 boot
~# e2label /dev/mmcblk0p2 rootfs
~# mount -oremount,rw /boot
~# cp -a /boot/cmdline.txt /boot/cmdline_org.txt

/boot/cmdline.txt:

・・・・・ init=/sbin/myinit fastboot ro

~# mount -oremount,ro /boot


/etc/fstab_tmpfsroot:

# tmpfsroot用の/etc/fstab
# proc
proc          /proc    proc  defaults             0 0
# 軟弱なFAT領域はroマウント
LABEL=boot    /boot    vfat  ro,defaults          0 2
# rootfsはコメントアウト
#LABEL=rootfs  /        ext4  ro,defaults,noatime  0 1
# /tmpもroになるのでtmpfsにする
tmpfs         /tmp     tmpfs defaults             0 0


/sbin/myinit:

#!/bin/bash
## /tmpfsrootが存在すればtmpfsrootを構築する
if [ -d /tmpfsroot ] ; then
    ## tmpfsを作成
    mount -t tmpfs tmpfs /tmpfsroot
    ## 主要rwフォルダをtmpfsにコピーし、bindマウントで元位置に戻す。
    ## tmpfs容量(500MB)より小さくなるように調整すること。/varは別処置する。
    #for d in etc home root; do
    for d in etc root; do
        cp -a /${d} /tmpfsroot/
        mount -obind /tmpfsroot/${d} /${d}
    done
    ## /varは選択的に処置
    mkdir /tmpfsroot/var
    find /var/ -type d | cpio -pdm /tmpfsroot/
    find /var/ -type l | cpio -pdm /tmpfsroot/
    rm -rf /tmpfsroot/var/lib/*
    cp -a /var/lib/* /tmpfsroot/var/lib/
    mount -obind /tmpfsroot/var /var
    ## tmpfsroot用の/etc/fstabを設定。tmpfsroot化済みのため元ファイルは消えない。
    [ -e /etc/fstab_tmpfsroot ] && mv -f /etc/fstab_tmpfsroot /etc/fstab
    ## tmpfsroot用のログインロゴがあれば設定
    [ -e /etc/issue_tmpfsroot ] && mv -f /etc/issue_tmpfsroot /etc/issue
    [ -e /etc/motd_tmpfsroot  ] && mv -f /etc/motd_tmpfsroot  /etc/motd
fi
## Start Systemd
exec /sbin/init

~# chmod +x /sbin/myinit ← 忘れずに!


元の環境に戻す場合:
~# mount -oremount,rw /boot
~# cp -a /boot/cmdline.txt /boot/cmdline_tmpfsroot.txt
~# cp -a /boot/cmdline_org.txt /boot/cmdline.txt
~# mount -oremount,ro /boot
~# reboot


デコレーション(任意):

/etc/issue_tmpfsroot:

 ______    _______  _______  _______  _______  ___   _______  __    _
|    _ |  |   _   ||       ||       ||  _    ||   | |   _   ||  |  | |
|   | ||  |  |_|  ||  _____||    _  || |_|   ||   | |  |_|  ||   |_| |
|   |_||_ |       || |_____ |   |_| ||       ||   | |       ||       |
|    __  ||       ||_____  ||    ___||  _   | |   | |       ||  _    |
|   |  | ||   _   | _____| ||   |    | |_|   ||   | |   _   || | |   |
|___|  |_||__| |__||_______||___|    |_______||___| |__| |__||_|  |__|

↑ シリアルコンソールでないと見れない。

/etc/motd_tmpfsroot:

  ,--.                    ,---.                              ,--.
,-'  '-.,--,--,--. ,---. /  .-' ,---. ,--.--. ,---.  ,---. ,-'  '-.
'-.  .-'|        || .-. ||  `-,(  .-' |  .--'| .-. || .-. |'-.  .-'
  |  |  |  |  |  || '-' '|  .-'.-'  `)|  |   ' '-' '' '-' '  |  |
  `--'  `--`--`--'|  |-' `--'  `----' `--'    `---'  `---'   `--'
                  `--'

↑ 環境が分かりやすくなるので推奨。

Ubuntu Mate 18.04 でScreenlets

組込開発のLinuxホストをCentOS7からUbuntu Mate(マテ茶)18.04 LTSに徐々に移すことにした。理由はいろいろあるが、Ubuntuフレーバの中でも何にするか紆余曲折した。最後の決め手はデスクトップのカスタマイズがしやすく遊び心を満たしてくれること、マテ茶調のデザインが気に入ったこと、軽いこと、ラズパイ向けの対応もあるということだった。かつて夢中になったCompiz FusionでのキューブデスクトップとファイヤーもVirtualBoxかラズパイでいずれやるつもり。
Screenletsガジェットは個人的には必須のアイテム。ガジェットはセキュリティリスクが多分にあって全く推奨できず、標準パッケージはもはや存在しないが、閉塞的な開発PCや仮想マシンでの限定的な用途であれば問題無いであろう、たぶん。
以下、Screenletsの無理矢理インストールの手順メモである。何か抜けはあるかもしれない。

cd Downloads
wget https://launchpad.net/screenlets/trunk/0.1.7/+download/screenlets-0.1.7.tar.bz2
tar xaf screenlets-0.1.7.tar.bz2
cd screenlets-0.1.7/
sudo make install
cd ..

sudo apt install python-beautifulsoup python-cairo python-gtk2 libwnck22  libwnck-common python-gobject-2 python-tz python-dbus

wget http://launchpadlibrarian.net/328363369/python-wnck_2.32.0+dfsg-4_amd64.deb
wget http://launchpadlibrarian.net/328363368/python-rsvg_2.32.0+dfsg-4_amd64.deb

sudo dpkg -i python-*.deb

wget http://ftp.riken.jp/Linux/ubuntu/pool/universe/i/indiv-screenlets/screenlets-pack-basic_0.1.6-0ubuntu1_all.deb
sudo dpkg -i screenlets-*.deb

cd /usr/share/icons
sudo ln -s hicolor/scalable/apps/screenlets-tray.svg 
sudo ln -s hicolor/scalable/apps/screenlets.svg 

## 無理矢理インストールしたパッケージを名目上削除
sudo cp -a /usr/share/screenlets/screenlets-pack-basic /usr/local/src
sudo apt --fix-broken install -y  # ← screenlets-pack-basicが削除される
sudo mv /usr/local/src/screenlets-pack-basic  /usr/share/screenlets/

## 晴れて起動
cd
screenlets


f:id:t0a9n9a4k:20190216215425p:plain

備考:上記デモ画面では、バックグランドでCPU負荷を入れている。


関連:CentOS7のXFCE4環境でScreenletsガジェット - Linux放浪紀Ⅲ

神がかった舞い

私はフィギュアスケートはまず見ませんし、いつもならすぐにチャンネルを変えますが、たまたま見ていたこの時だけはテレビに釘付けになり、完全に魅了されてしまいました。曲と振りのマッチングが本当にすばらしいです。観客の声援・拍手の裏で、淡々と無表情に舞う姿に、なぜか涙が出そうになりました。

【フジテレビ公式】四大陸フィギュア2019<紀平梨花選手・女子フリー>ノーカット配信 - YouTube
2分過ぎのスピン後から60秒弱の流れは「a beautiful storm」そのもの。

最近、スポーツ選手の勝負時の精神状態に興味があるのですが、おそらくこのスケーティングのとき、彼女はゾーンに入っていたし、その状態に持っていったのでしょう。それともうひとつ、彼女は練習で左手薬指を負傷していたようですが、それで体の力が抜け、かえって良かったのかもしれません。昨年のロシアの動画も見ましたが、今回の方が動きがズムーズに見えます。

私も、プレゼンに望む際、準備万端で体調万全なときよりも、どこか体の調子が悪かったり、忙しくてプレゼンどころではないときほど、なぜかうまくいっていました。勝ちを意識せず、力が入りすぎない脱力の境地が、このあたりにありそうです。

急に強くなって大活躍中のテニスプレーヤーも、勝利目前で窮地に陥ったときは、勝ちを意識せず「私はロボットになる」として淡々とプレーしたようです。修羅場を超えるときの冷静さを、私も身につけたいものです。

IPv6無効化アラカルトと副作用

ホビー向けではIPv6無効化はしない方がよさそうというのが結論だが、無効化設定には、いろいろある。
① /etc/sysctl.confで設定

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

② /etc/modprobe.d/ipv6.confで設定(ファイル名は任意)

# Don't load ipv6 by default
alias net-pf-10 off
alias ipv6 off
# https://www.raspberrypi.org/forums/viewtopic.php?t=138899
options ipv6 disable_ipv6=1
blacklist ipv6

②は、Debian9 stretch amd64ではIPv6を無効化できない。それは、Kernel構築時の.configにおいて、CONFIG_IPV6=m → y となり、IPv6モジュールがKernelに埋め込まれたためだ。
一方で、ラズパイのRaspbian stretchでは、ここにある通りKernel外出しのモジュールで定義されており、IPv6をモジュール単位で根こそぎ無効化できるということだと思う。

ラズパイでは②の方が良いかもしれない。理由は、
$ netstat -na | grep tcp6
と打てば分かる。①の設定では、IPv6は確かに無効にはなっているが、アプリレベルではIPv6のポートが開いている。②はアプリレベルでも開いていない。

③ Kernel起動パラメータ ipv6.disable=1
パソコンなら/etc/default/grubに追記してinitrdを再生成、ラズパイなら/boot/cmdline.txtに追記する。


IPv6無効化の副作用:
Windowsや別Linuxホストからxrdp(リモートデスクトップ)でログインしたいケースで、正しく動作しない。Debian9 stretch amd64ではxrdpデーモンが起動しない。Raspbianでは、xrdpログイン画面は出るが、やはりひっかかる。
対策例ばこちら↓(要・ビルド)。 github.com

エアロビじゃなくてエアロ

まずはじめに、エアロ(ビ)の良いイメージを残すため勝手にリンクを貼らせていただきました <(_ _)> 。本当にクールですよね〜。
 動画1:クールなエアロ
このように面が変わり、差し込まれたら、私は地蔵になるかも・・・。


先日、バブル入社組のうち気の合う6人で飲みに行った。20年ぶりに再会できた同期もいて、とても懐かしいメンバ。当然、健康維持の話が出る。私が、エアロビで健康維持していると言ったら、20年前テニスで絶対的に強かった同期Aが、『・・・エアロビ ・・・・・ フッ w』と鼻で軽く笑い、ビールをすすり始めた。そのとき、『・・・』でのAの頭の中は、きっと20年前のイメージのまま、こんなんだったのだろう。

 動画2:ダサかっこわるいエアロビ
 * 衝撃的なダサさなので動画の埋込み表示は止めておいた。


まぁ、良くてこのあたりか。
 動画3:オリビア

20年前は、テニスでもまだシャツはズボンにインだったような気もする。その点も含め、弁明しようと思ったが、話題が次に流れて、それっきりだ。そもそも、「エアロビ」と言った私が悪かったのかもしれない。「ビ」を入れるとダサいイメージになる(特にアルコールの席では)。次からは「エアロ」と言ってみることにする。

ラズパイ:シャットダウンフリー tmpfs-chroot編

もし、手の届かない離島に電源ブチ切りラズパイを置くなら、私ならばoverlayもfuseも使いたくない。以下、/sbin/initでの対応を示すが、未完成である。シンボリックリンクを嫌う実装が何かあるようで、いずれ調査して解決する予定である。一方で、chrootは使わず、Stateless CentOS7でのやり方(=tmpfsでbind)で実装できている。下記でも起動はするし、SSHログインもできるが、現時点ではoverlay方式またはtmpfs-bind方式でのご利用を推奨する。

前提:準備①〜③が完了していること。fuseとoverlayは不要。

~# mkdir /tmpfsroot
~# touch /.tmpfsroot
~# dosfslabel /dev/mmcblk0p1 boot
~# e2label /dev/mmcblk0p2 rootfs

/tmpfsrootにユーザランド(rootfs)を構築し、chrootする。リードオンリーで良い領域はシンボリックリンクで対応する。アプリによっては、シンボリックリンクで対応したために正しく機能しないケースがある。/etc/fstab_tmpfsrootは、/tmpfsroot/etc/fstabにコピーされる。

/etc/fstab_tmpfsroot(rw→ro):

# tmpfsroot用の/etc/fstab
proc         /proc    proc  defaults             0 0
# 軟弱なFAT領域はroマウント
LABEL=boot   /boot    vfat  ro,defaults          0 2
# rootfsを/MicroSDへroマウント
LABEL=rootfs /MicroSD ext4  ro,defaults,noatime  0 1
# LABEL=logを刻印したext4メディアにログ保存するならコメントアウト
#LABEL=log   /var/log ext4  defaults,noatime     0 0


~# rm /sbin/init

Under Construction!
基本動作確認はしているが改善余地があり、後日フォロー予定。

/sbin/init:

#!/bin/sh
## /home, /root, /etcは、総メモリ容量の1/2を超える場合は、事前に調整すること。
## 特に/homeは要注意。確認方法: cd /; du --max-depth 1 -h 
## $DISKは定義しない(rootfsは/boot/cmdline.txtのパラメータでマウントされている)。

ramdisksize=500M
# DISK=/tmpfsroot/MicroSD

if [ -d /tmpfsroot ] && [ -e /.tmpfsroot ]; then

    ## /tmpfsrootに主要構成を構築
    mount -t tmpfs -o size=${ramdisksize} tmpfs /tmpfsroot

    ## フォルダ作成
    echo "Creating directories..."
    for d in boot dev media mnt opt proc run sys tmp usr var MicroSD; do
        mkdir /tmpfsroot/${d}
    done

    ## 微調整
    chmod 1777 /tmpfsroot/tmp
    echo > /tmpfsroot/fastboot

    ## rwエリアをコピー
    ## *** メモリの1/2容量を超えないこと! ***
    echo -n "Copying files, directories..."
    #for d in etc root home srv; do
    for d in etc root srv; do
        echo -n ".. "
        cp -a ${DISK}/${d} /tmpfsroot
    done
    # /etc/fstabを調整
    [ -e /tmpfsroot/etc/fstab_tmpfsroot ] && mv -f /tmpfsroot/etc/fstab_tmpfsroot /tmpfsroot/etc/fstab

    ## roエリアをシンボリックリンク
    for d in bin sbin lib; do
        ln -s /MicroSD/${d} /tmpfsroot/${d}
    done

    ## /usrを処置(/usr/localだけtmpfs)
    for d in bin games include lib man sbin share src; do
        ln -s /MicroSD/usr/${d} /tmpfsroot/usr/${d}
    done
    cp -a ${DISK}/usr/local /tmpfsroot/usr

    ## /varの処置:ディスクの/varの構成のみをコピー
    cd ${DISK}/var
    for d in `ls -l | awk '$1 ~ /d/ {print $9 }' `; do
        DIR_NAME=`basename ${d}`
        if [ ${DIR_NAME} = "lib" ]; then
            #ln -s /MicroSD/var/lib /tmpfsroot/var/lib
            mkdir /tmpfsroot/var/lib
        else
            find ${DIR_NAME} -type d | cpio -pdm /tmpfsroot/var/
            find ${DIR_NAME} -type l | cpio -pdm /tmpfsroot/var/
        fi
    done
    ## /var/libの処置
    cd ${DISK}/var/lib
    for d in `ls -l | awk '$1 ~ /d/ {print $9 }' `; do
        DIR_NAME=`basename ${d}`
        if [ ${DIR_NAME} = "systemd" ] || [ ${DIR_NAME} = "nfs" ]; then
            # rwフォルダはtmpfsrootにコピー
            cp -a ${DISK}/var/lib/${DIR_NAME} /tmpfsroot/var/lib/${DIR_NAME}
        else
            # 他はSymbolic Linkで対応
            ln -s /MicroSD/var/lib/${DIR_NAME} /tmpfsroot/var/lib/${DIR_NAME}
        fi 
    done
    cd

    ## fstabに/var/logの定義があればマウント
    mount -T /tmpfsroot/etc/fstab /var/log

    ## switch_root
    mount -o bind /sys /tmpfsroot/sys
    mount -o bind /dev /tmpfsroot/dev/
    mount -t proc proc /tmpfsroot/proc
    #mount -o bind / /tmpfsroot/MicroSD
    cd /tmpfsroot
    pivot_root . MicroSD
    exec chroot . /lib/systemd/systemd

    #exec switch_root /tmpfsroot /lib/systemd/systemd "$@" </tmpfsroot/dev/console >/tmpfsroot/dev/console
    #exec /usr/lib/klibc/bin/run-init /tmpfsroot /lib/systemd/systemd
    #exec /usr/lib/klibc/bin/run-init /tmpfsroot /lib/systemd/systemd "$@" </tmpfsroot/dev/console >/tmpfsroot/dev/console
    #exec chroot /tmpfsroot /lib/systemd/systemd

else
    ## 元のsystemdを起動する
    exec /lib/systemd/systemd
fi

echo "Something went badly wrong in the /sbin/init."

~# chmod +x /sbin/init

ラズパイ:シャットダウンフリー overlay編(fuse無し)

Linuxで最初に動くプログラムである/sbin/initは、/lib/systemd/systemdへのシンボリックリンクになっているが、これをスクリプトにして調整事項を挟み込んでしまえば、fuseは不要となる。fuse+overlay編よりも調整の手間が少ないので、私はこちらの方が好きだが、こちらも実績は薄いので、自己責任で、ラズパイが手に届く範囲での利用を推奨する。
なお、元の環境でapt updateを実施すると、/sbin/initはシンボリックリンクに戻ることがある。これで環境が崩れるのを避けるため、ここでは、/sbin/myinitを起動調整スクリプトとし、/boot/cmdline.txtに「init=/sbin/myinit fastboot ro」を追記することとする。fstabもoverlay専用のものを作り、元のfstabには触れないこととする。

前提:準備①〜③、⑤が完了していること。fuseは不要。

~# dosfslabel /dev/mmcblk0p1 boot
~# e2label /dev/mmcblk0p2 rootfs

~# mount -oremount,rw /boot
~# cp -a /boot/cmdline.txt /boot/cmdline.txt.orig

/boot/cmdline.txt:

・・・・・ init=/sbin/myinit fastboot ro


/etc/fstab_overlay:

# overlay用の/etc/fstab
# proc
proc          /proc    proc  defaults             0 0
# 軟弱なFAT領域はroマウント
LABEL=boot    /boot    vfat  ro,defaults          0 2
# rootfsはコメントアウト
#LABEL=rootfs  /        ext4  ro,defaults,noatime  0 1
# /tmpもroになるのでtmpfsにする
tmpfs         /tmp     tmpfs defaults             0 0


/sbin/myinit:

#!/bin/bash
## /.overlayが存在すればoverlayにする。
if [ -e /.overlay ] && [ -d /overlay ] ; then
    ## /var/logのツリー構成だけを退避
    find /var/log/ -type d | cpio -pdm /dev/shm/
    find /var/log/ -type l | cpio -pdm /dev/shm/
    ## overlayのrw実体となるtmpfsを作成
    mount -t tmpfs tmpfs /overlay
    ## 主要フォルダをoverlay化
    for d in usr etc home root var; do
        mkdir -p /overlay/${d} /overlay/${d}_rw
        OPTS="-o lowerdir=/${d},upperdir=/overlay/${d},workdir=/overlay/${d}_rw"
        mount -t overlay ${OPTS} overlay /${d}
    done
    ## overlay用の/etc/fstabを設定。overlay化済みのため元ファイルは消えない。
    [ -e /etc/fstab_overlay ] && mv -f /etc/fstab_overlay /etc/fstab
    ## overlay用のログインロゴがあれば設定
    [ -e /etc/issue_overlay ] && mv -f /etc/issue_overlay /etc/issue
    [ -e /etc/motd_overlay ] && mv -f /etc/motd_overlay /etc/motd
    #### 任意Option-A:退避した/var/logをtmpfsに移動
    mount -t tmpfs tmpfs /var/log
    mv /dev/shm/var/log/* /var/log/
    rm -rf /dev/shm/log
    #### 任意Option-B;退避した/var/logをoverlayfsに移動
    ## rm -rf /var/log
    ## mv /dev/shm/var/log /var/
fi
## Start Systemd
exec /lib/systemd/systemd

~# chmod +x /sbin/myinit ← 忘れずに!


シャットダウンフリー環境へ移行:
~# mkdir /overlay
~# touch /.overlay
~# reboot


元の環境に戻す:
~# mount -oremount,rw /
~# rm /.overlay
~# reboot
または、/boot/cmdline.txtを元に戻してreboot。



$HOME/.bashrcへの追記(任意):

findmnt /etc | grep overlay > /dev/null
[ $? == 0 ] && printf "\n<<<< The Overlay Environment! >>>>\n\n"




2019-02-16 少し改良しました。