Raspberry Piの/tmp使用率が100%、でもファイルはない

自宅の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にたどり着くのかということ。これは調べても出てきませんでした。