自宅のRaspberry Piを24時間稼働させているのですが、このところ不調です。
SDカードの書き込み回数を減らす目的で、RAMディスクの一つであるtmpfsを導入していますが、SSHでRaspberry Piへログインすると、Tab補完時にこんなメッセージが出ます。
pi@raspberrypi:~ $ cd -bash: cannot create temp file for here-document: No space left on device
/tmp の空き容量が無いと想像できるので、dfコマンドでシステムディスクの空き容量を確認しました。
pi@raspberrypi:~ $ df -m -H
Filesystem Size Used Avail Use% Mounted on
/dev/root 8.0G 1.5G 6.2G 20% /
devtmpfs 480M 0 480M 0% /dev
tmpfs 485M 0 485M 0% /dev/shm
tmpfs 485M 49M 436M 11% /run
tmpfs 5.3M 4.1k 5.3M 1% /run/lock
tmpfs 485M 0 485M 0% /sys/fs/cgroup
tmpfs 34M 0 34M 0% /var/tmp
tmpfs 68M 107k 68M 1% /var/log
tmpfs 68M 68M 0 100% /tmp
/dev/mmcblk0p1 43M 22M 21M 52% /boot
たしかに/tmpの使用率が100%となっています。/tmpにどのようなサイズのファイルがあるか調べるにはduコマンドが簡単です。
pi@raspberrypi:~ $ du -h /tmp
0 /tmp/.Test-unix
0 /tmp/.font-unix
0 /tmp/.XIM-unix
0 /tmp/.ICE-unix
0 /tmp/.X11-unix
0 /tmp
左に表示される数字が/tmp配下にあるディレクトリの容量なのですが、なぜかゼロとなっています。そうなると、見えないけれど消せないファイルがこのディレクトリ内にあるのでは?と想像できます。
ひとつ思い当たるのが、バックグラウンドで動いているプロセスが掴んでいるファイルです。プロセスがどのファイルを掴んでいるかを見るにはlsofコマンドが便利です。
Raspbianにはデフォルトでインストールされていないためapt-getで入れます。
pi@raspberrypi:~ $ sudo apt-get install lsof
そのままlsofコマンドを使っても良いですが、大量に表示されるためgrepで/tmpを使用しているプロセスのみ絞り込みます。
pi@raspberrypi:~ $ lsof | grep /tmp
save_sens 565 pi 2u REG 0,31 67108864 9016 /tmp/tmpfSHPqfy (deleted)
sleep 31699 pi 2u REG 0,31 67108864 9016 /tmp/tmpfSHPqfy (deleted)
左側に/tmp以下を使用しているプロセス名が表示され、右側にそのプロセスが掴んでいるファイルが表示されます。
なんということでしょう。ここに表示されている”save_sens”は私が作ったシェルスクリプト「save_sensor.sh」のことで、Raspberry Piへ接続したセンサーの値をデータベースへ保存する働きをしています。このスクリプトは常にバックグラウンドでループ動作していますが、/tmpを使うようにプログラムした覚えはありません。
とりあえず、このプロセスを切りましょう。
pi@raspberrypi:~ $ ps -A | grep save_sens
565 ? 00:03:59 save_sensor.sh
pi@raspberrypi:~ $ kill -9 565
pi@raspberrypi:~ $ df -m -H
Filesystem Size Used Avail Use% Mounted on
/dev/root 8.0G 1.5G 6.2G 20% /
devtmpfs 480M 0 480M 0% /dev
tmpfs 485M 0 485M 0% /dev/shm
tmpfs 485M 49M 436M 11% /run
tmpfs 5.3M 4.1k 5.3M 1% /run/lock
tmpfs 485M 0 485M 0% /sys/fs/cgroup
tmpfs 34M 0 34M 0% /var/tmp
tmpfs 68M 107k 68M 1% /var/log
tmpfs 68M 0 68M 0% /tmp
/dev/mmcblk0p1 43M 22M 21M 52% /boot
プロセス終了後、もう一度dfでディスク容量を見てみると、/tmp使用率が0%になりました。やはり、このスクリプトが悪さをしているようです。
さらに調べてみると、このスクリプトの実行方法に問題があり、次のようになっていました。
# センサー監視&記録ツールの起動
${HOME}/save_sensor.sh > /dev/null &
ぐぬぬ、、標準出力は /dev/null になっているけど、標準エラーの処理がありません。センサーへのアクセスができないときに標準エラーをよく出すプログラムだったので、エラーが/tmpに溜まり、容量がいっぱいになったと推測されます。
標準エラーも /dev/nullへ出力するよう、次のように実行文を修正したところ、/tmpが容量不足となることはなくなりました。
# センサー監視&記録ツールの起動
${HOME}/save_sensor.sh >/dev/null 2>&1 &
最後に疑問として残るのは、行き場のない標準エラーは/tmpにたどり着くのかということ。これは調べても出てきませんでした。