Raspberry PiのSDカードが壊れた!寿命を延ばす方法 5+1選!

目次

ラズベリーパイ、完全に沈黙

ラズパイで音声合成を使って喋らせることができるようになったので、調子に乗って「時報女」さんのように数ヶ月ずっと喋らせていたら、つい先日から沈黙してしまいました。

キーボード入力も何も受け付けない、、、
そして、電源を切ったら最後、真っ暗画面から復帰せず。

ちーん。

これは、SDカードがお亡くなりなってしまったな。。。

同僚からは、長期運用するにはSDカードはヤバイヨ!と言われていたので、ついに来たかと。

ということで、今回はラズベリーパイ用のマイクロSDカードの寿命を延ばす方法、

名付けて、

Re: ゼロから始めるラズパイ生活

※あんたも好きね〜w と言われそうですが、実際に再インストールから始めたので方向性は合っているのです(`・ω・´)キリッ

 

実施環境

Raspberry Pi 3B Raspbian Jessie

uname -r
4.9.35-v7+

念のため更新。

sudo apt-get update
sudo apt-get upgrade

 

寿命を延ばす方法5選!(+1番外編)

ネットで先駆者の情報を渉猟すること小1時間。

ざっくりまとめると、

  • (1)スワップを無効にする
  • (2)ログファイルの一次作成場所をtmpfs(Ramdisk上)にする
  • (3)ログ出力を減らす
  • (4)テンポラリ領域をtmpfs(Ramdisk上)にする
  • (5)容量の大きなSDカードを使う
  • (番外編)fstabでcommitの時間を長く設定する(ちょっとリスク高め)

という方法がありました。

では、具体的な方法を紹介します。

 

(1)スワップを無効にする

メモリが足りないときに一時的に作られるスワップファイル。ラズパイではそこまでメモリを食う作業をやらないので、スワップしている所はほとんど見たことありません!

試しにどのくらい使っているか見てみると、

free -h
             total       used       free     shared    buffers     cached
Mem:          923M       286M       636M        29M        23M       173M
-/+ buffers/cache:        89M       833M
Swap:          99M         0B        99M

全然使っていないことがわかります。(元々100MB程度しか確保さていない!)
ということで、スワップを無効化していきます。

sudo swapoff --all
free -h
             total       used       free     shared    buffers     cached
Mem:          923M       296M       627M        29M        24M       174M
-/+ buffers/cache:        96M       826M
Swap:           0B         0B         0B

これで一旦スワップ領域を無くすことができますが、再起動すると元に戻ってしまうためサービスを止めます。

ラズパイのスワップファイルは dphys-swapfile を使っていて自動起動になっています。

insserv -s | grep dphys-swapfile
S:03:2 3 4 5:dphys-swapfile

自動起動を停止します。

 sudo insserv -r dphys-swapfile

※systemctlコマンドの場合はこちら。

 sudo systemctl stop dphys-swapfile
 sudo systemctl disable dphys-swapfile

 systemctl status dphys-swapfile
● dphys-swapfile.service - LSB: Autogenerate and use a swap file
   Loaded: loaded (/etc/init.d/dphys-swapfile)
   Active: inactive (dead)

再起動して停止できているか確認します。

sudo reboot
free -h

以上で完了です。

元に戻す場合は、サービスを再開します。

 sudo systemctl enable dphys-swapfile
 sudo systemctl start dphys-swapfile
 systemctl status dphys-swapfile

ref. Raspberry Pi -RASPBIAN- のswapを無効化

 

 

(2)テンポラリ領域をtmpfs(Ramdisk上)に設定する

fstabを修正して、/tmp と /var/tmp をtmpfs(Ramdisk上)に設定します。

sudo vim /etc/fstab

下記の2行を追加します。

tmpfs           /tmp            tmpfs   defaults,size=32m,noatime,mode=1777  0       0
tmpfs           /var/tmp        tmpfs   defaults,size=16m,noatime,mode=1777  0       0

後は、SDカード上の /tmp と /var/tmp を消して、再起動すればOKです。

sudo rm -rf /tmp
sudo rm -rf /var/tmp
sudo reboot

 

(3)ログ出力を減らす

たくさんのログが出力されていますが、使っていないサービスの出力を減らしてみます。
/etc/rsyslog.conf を編集して、RULES以下に記載されている設定の先頭に#をつけてコメントアウトします。

※ログファイルは動作がおかしい時に問題を解決する糸口を掴むためにとても大事なので、時々ONにして確認することをオススメします。

sudo vim /etc/rsyslog.conf

基本的なログの中で、使わないモノをコメントアウト。

###############
#### RULES ####
###############

#daemon.*      -/var/log/daemon.log
kern.*        -/var/log/kern.log
#lpr.*       -/var/log/lpr.log
#mail.*        -/var/log/mail.log
user.*        -/var/log/user.log

メール、InterNetNewsは使っていないので、

#mail.info     -/var/log/mail.info
#mail.warn     -/var/log/mail.warn
#mail.err      /var/log/mail.err

#news.crit     /var/log/news/news.crit
#news.err      /var/log/news/news.err
#news.notice     -/var/log/news/news.notice

デバッグも。

#*.=debug;\
#  auth,authpriv.none;\
#  news.none;mail.none -/var/log/debug

修正が終わったら、サービスを再起動します。

sudo systemctl restart rsyslog

 

(4)ログファイルの一次作成場所をtmpfs(Ramdisk上)にする

ログファイルの作成場所をtmpfsにすることで、SDカードへのアクセス回数を減らします。ただし、このままだと電源を落とすと消えてしまうので、定期的にバックアップする仕掛けも作っておきます。

やることをざっくりまとめると、

  1. /var/log を tmpfs としてマウントする(fstab)
  2. 起動時に /var/log の構造を作る(init.d、復活の呪文)
  3. 終了時にログのバックアップを取る(init.d、rsync)
  4. 定期的にログのバックアップを取る(crontab)

となります。

既存の/var/log 構造を復活させるためのスクリプトは、インストールされているサービスによって異なってくるため、汎用的に対処できるよう「復活の呪文(復元するためのスクリプト)を自動生成するスクリプト」も作成しました。

※作業しやすいようファイルを分割し、ユーザーディレクトリで作業しています。自前の環境で実行する際には、ユーザーを読み替えたり、/usr/local/bin にスクリプトを置くなど適宜調整してください。

準備

作業前にバックアップを取っておきます。

sudo mkdir -p /back/var-log
sudo cp -r /var/log/* /back/var-log/

/var/log/ にあるログファイルやサービス用ディレクトリを調べて復元するためのリストを作成します。

#ログファイル
stat --format='%a %U:%G %n' `find /var/log/ -maxdepth 1 -mindepth 1 -type f` | grep -v '.gz\|.log$\|1$\|.old$' > ~/logFiles

#ログディレクトリ
stat --format='%a %U:%G %n' `find /var/log/ -maxdepth 1 -mindepth 1 -type d` > ~/logDirs

 

このリストを使って、復活の呪文を生成するスクリプト(make-init-logfiles.sh) を作成します。

vim ~/scripts/make-init-logfiles.sh

ファイルの中身:

#!/bin/sh

# 出力するスクリプトファイル
fScr="${HOME}/scripts/setup-logs.sh"

#ログファイル
stat --format='%a %U:%G %n' `find /var/log/ -maxdepth 1 -mindepth 1 -type f` | grep -v '.gz\|.log$\|1$\|.old$' > ~/logFiles
cp -i ~/logFiles ~/logFiles.bak

#ログディレクトリ
stat --format='%a %U:%G %n' `find /var/log/ -maxdepth 1 -mindepth 1 -type d` > ~/logDirs
cp -i ~/logFiles ~/logDirs.bak

echo "#!/bin/sh" > $fScr
echo "\n### Make directories ###" >> $fScr

cat ~/logDirs | while read line
do
  echo "##" >> $fScr
  echo $line | awk '{print "mkdir -p " $3}' >> $fScr
  echo $line | awk '{print "chmod " $1 " " $3}' >> $fScr
  echo $line | awk '{print "chown " $2 " " $3}' >> $fScr
done

echo "\n### Make files ###" >> $fScr

cat ~/logFiles | while read line
do
  echo "##" >> $fScr
  echo $line | awk '{print "touch " $3}' >> $fScr
  echo $line | awk '{print "chmod " $1 " " $3}' >> $fScr
  echo $line | awk '{print "chown " $2 " " $3}' >> $fScr
done

# 実行権をつけておく
chmod +x $fScr

このコマンドを実行すると、最新の/var/log に必要なファイルやフォルダを作成するスクリプトができあがります。

sh ~/scripts/make-init-logfiles.sh

次に、起動・終了時に実行するスクリプトを作成していきます。

1) init.d にスクリプトを配置する

起動・終了時に呼び出されるスクリプトを作成します。

sudo touch /etc/init.d/setup-tempfs-logs
sudo chmod +x /etc/init.d/setup-tempfs-logs
sudo vim /etc/init.d/setup-tempfs-logs

setup-tempfs-logs の中身:

#!/bin/sh
### BEGIN INIT INFO
# Provides:          setup-tempfs-logs
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Setup tempfs log files
### END INIT INFO
case "$1" in
  start|"")
    sh /home/pi/scripts/setup-logs.sh 2>&1 >/dev/null
    ;;
  stop)
    sh /home/pi/scripts/backup-logs.sh 2>&1 >/dev/null
    ;;
  *)
    echo "Usage: /etc/init.d/setup-tempfs-logs [start|stop]" >&2
    exit 3
    ;;
esac

起動時に実行するスクリプトは、先ほど生成したsetup-logs.shstartに指定して、必要なログファイルの準備を行うようにしています。

終了時に実行するスクリプトとして、バックアップファイルを作成するスクリプトbackup-logs.shを作成して、stopに指定しています。

まず、バックアップ先を作成します

sudo mkdir -p /back/logs

スクリプトを作成します。中身はrsyncです。

vim /home/pi/backup-logs.sh
#!/bin/sh
LOG="/back/logs/backup-history.txt"
sudo sh -c "date > $LOG"
sudo sh -c "rsync -av /var/log/* /back/logs/ >> $LOG"

試しに実行します

chmod +x backup-logs.sh
sudo ./backup-logs.sh

うまく実行されていれば、/back/logs/ にログファイルとbackup-history.txtができていると思います。

2) boot時に実行されるよう登録

sudo insserv -d setup-tempfs-logs

確認

sudo ls /etc/rc*.d/*setup-tempfs-logs

ファイル(シンボリックリンク)が表示されていればOKです。

3) 定期的に実行されるようにcronに登録

毎時0分にバックアップするようcronを設定します。

sudo crontab -e
0 * * * * /home/pi/scripts/backup-logs.sh

4) tmpfsでマウントするように設定

/etc/fstab を編集して、tmpfsの1行を追加します。

sudo vim /etc/fstab
tmpfs           /var/log        tmpfs   defaults,size=32m,noatime,mode=0755  0       0

5) 既存の /var/log を削除して、再起動

sudo rm -rf /var/log
sudo reboot

 

(5)容量の大きなSDカードを使う

容量が少ないと、同じ場所を何度も読み書きする機会が増えるので、なるべく容量の大きなSDカードを使うと良いそうです(※らしい。まだ実感無し)。

(番外編)fstabでcommitの時間を長く設定する(ちょっとリスク高め)

ラズパイの掲示板で発見しました。システム領域のマウント設定で、commit値を大きめに設定するというものです。

cat /etc/fstab |grep mmcblk | grep ext4
/dev/mmcblk0p7  /               ext4    defaults,noatime  0       1

これを、このように書き換えます。

/dev/mmcblk0p7  /               ext4    defaults,noatime,commit=290  0       1

290秒(4分50秒)毎にファイルを書き込むようになります。
man mount によるとdefaultは30秒なので、約10倍書き込む頻度が減ることになります。
なお、300秒以上はwarningが表示されるとのことなので290としています。

この間に電源が落ちると変更は失われてしまいますので、使い方によって適宜調整したほうが良いでしょう。

ref. Script to extend SD card life

 

まとめ

ラズベリーパイのシステム用マイクロSDカードへの書込を減らして寿命を延ばす方法を紹介しました。

何事も、備えあれば憂いなし。

寿命を延ばした上でさらにSDカードのバックアップを取っておけば安心です。
その辺りはまた次の機会にまとめたいと思います。

それでは、良いラズベリーパイ生活を!

 

参考にしたサイト