Raspberry Piにシャットダウンとリブートボタンを設置する

WebサーバーとしてRaspberry Piを動かしているとたまにサーバーがダウンしてアクセスできなくなることがあります。

SSHからもアクセスできないため、いつもしかたなくUSB電源を引っこ抜きます。今までUSB電源引っこ抜きても問題はなかったのですが、精神的に気分が悪いのでRaspberry Piにシャットダウンとリブートボタンを設置することにしました。

シャットダウンとリブートボタンを設置した完成図

超適当に配線図を描きました。

押しボタンを長押し(3秒以上)するとシャットダウンになって、ポチっと押すとリブートになります。シャットダウンのときはLEDが赤く一瞬光ります。リブートのときはLEDが数秒赤く光り続けます。

材料
タクトスイッチ(押しボタンスイッチ) 1個10円
LED 1個10円
抵抗 100オーム 2個で4円
ミニブレッドボード 1個で100円
ジャンパーケーブルか配線ケーブル 2本で10円
・ピンヘッダーか抵抗の足 2個で1円

材料費的には150円くらいでシャットダウンとリブートボタンをつけることができます。LEDと抵抗と配線ケーブル(またはジャンバーケーブル)だけ必須です。あとは手動でやれば何とかなりますが、タクトスイッチやミニブレッドボードはあったほうがいいです。

そんなこんなで組み上げたのが下記の写真です。

下のほうにあるブレッドボードにシャットダウンとリブートの押しボタンとLEDが設置してあります。小さいブレッドボードが品切れだったので、少し大きめなブレッドボードを使いました。

スイッチ側にある抵抗は比較的どんな数値でも大丈夫です。100オームから1kオーム以内の抵抗を入れておけばいいと思います。LED側にある抵抗は60オームから200オームの抵抗を入れておけば良いです。それで普通に光ります。

シャットダウンとリブートボタンのプログラム

参考サイト:Raspberry Pi shutdown/reboot button

参考サイトのプログラムにプルアップを設定して、スイッチを押したあとにLEDが光るようにしました。シャットダウンなら一瞬、リブートなら数秒光る感じになります。

押しボタンの入力用にGPIO6(Pin31)、LEDの点灯用にGPIO5(Pin29)を使いました。開いているGPIOを適当に使えばいいです。

シャットダウンとリブートボタンのプログラム

1vim switch.py
2 
3import RPi.GPIO as GPIO
4import time
5import os
6 
7GPIO.setmode(GPIO.BCM)
8GPIO.setup(6,GPIO.IN,pull_up_down=GPIO.PUD_UP)
9GPIO.setup(5,GPIO.OUT)
10GPIO.output(5,GPIO.LOW)
11 
12button_previous = 1
13button_current = 1
14brojac = 0
15flag_pressed = 0
16 
17while True:
18  button_current = GPIO.input(6)
19  flag_pressed = button_previous + button_current
20 
21  if (not(flag_pressed)):
22    brojac += 1
23  else:
24    brojac = 0
25 
26  if(button_current and (not button_previous)):
27    GPIO.output(5,GPIO.HIGH)
28    os.system("sudo shutdown -r now")
29  if((not flag_pressed) and brojac >= 100):
30    GPIO.output(5,GPIO.HIGH)
31    os.system("sudo shutdown -h now")
32    break
33 
34  button_previous = button_current
35  time.sleep(0.03)
36 
37GPIO.cleanup()

最後のGPIO.cleanup()はいらないんじゃないかと思ったりするけど、まぁ動くから放置です。

このプログラム(switch.py)を保存して実行します。

1sudo python switch.py

押しボタンをポチッと押すとLEDが数秒点灯してリブートします。押しボタンを3秒間押し続けるとLEDが一瞬光ってシャットダウンします。

次に起動時に押しボタンプログラムが自動起動するように設定します。

何かプログラムを間違えている状態で自動起動を設定するとリブートまたはシャットダウンの無限ループに陥る可能性があるので、まず最初に手動で実行してから問題ないようなら自動起動の設定を行いましょう。ここ重要です! 念のためRaspberry PiのマイクロSDカードのバックアップも取っておくといいと思います。

自動起動の設定

1sudo vim /etc/rc.local
2 
3//exit 0の前に記載する
4 
5sudo python /home/your_username/switch.py &
6exit 0

これで次からはスイッチプログラムは起動時に実行されるので手動で実行しなくてもOKです。

Raspberry Piにシャットダウンとリブートボタンを設置するのは若干面倒くさそうだなーと思っていましたが、実際にやってみると簡単にできました。

シャットダウンとリブートボタンのプログラムの別バージョン(割り込み)

while Trueでひたすらボタンが押されていないかをチェックし続けさせていましたが、割り込みを使うとチェックし続ける必要がなくなります。

たぶんこんな感じで動くプログラム

1vim switch.py
2 
3import RPi.GPIO as GPIO
4import time
5import os
6 
7GPIO.setmode(GPIO.BCM)
8GPIO.setup(6,GPIO.IN,pull_up_down=GPIO.PUD_UP)
9GPIO.setup(5,GPIO.OUT)
10GPIO.output(5,GPIO.LOW)
11 
12button_previous = 1
13button_current = 1
14brojac = 0
15flag_pressed = 0
16 
17 
18try: 
19  GPIO.wait_for_edge(6, GPIO.FALLING)
20 
21  while True:
22    button_current = GPIO.input(6)
23    flag_pressed = button_previous + button_current
24 
25    if (not(flag_pressed)):
26      brojac += 1
27    else:
28      brojac = 0
29 
30    if(button_current and (not button_previous)):
31      GPIO.output(5,GPIO.HIGH)
32      os.system("sudo shutdown -r now")
33    if((not flag_pressed) and brojac >= 100):
34      GPIO.output(5,GPIO.HIGH)
35      os.system("sudo shutdown -h now")
36      break
37 
38    button_previous = button_current
39    time.sleep(0.03)
40 
41except KeyboardInterrupt: 
42  GPIO.cleanup()
43 
44GPIO.cleanup()

実際にチェックはしていませんが、たぶんこれで動くと思います。

ずっとwhileループをさせるよりも割り込みの方が負荷が少ないと思うので、負荷を減らしたいときなんかは割り込み用のプログラムを試してみてください。

再掲(“さいかつ”ではなく”さいけい”)

スイッチプログラムは何か間違えている状態で自動起動を設定してしまうとリブートまたはシャットダウンの無限ループに陥る可能性があります。

まず自動起動を解除(コメントアウト)して、最初に手動で実行してから問題ないようなら自動起動の設定を行いましょう。ここ重要です!

念のためRaspberry PiのマイクロSDカードのバックアップも取っておくといいと思います。

Raspberry Piにシャットダウンとリブートボタンを設置する” への1件のコメント
  1. aono より:

    楽しく拝見させて頂いております。

    私もラズパイでWEBサーバーを立ち上げようとしているのですが、
    WEBサーバーが落ちる現象というのは頻発するものなのでしょうか?
    またその原因はわかっていますでしょうか?

    記事からはずれた質問になりますが、
    よろしければご回答よろしくお願いします。

    • kyosuke より:

      1台のPi2でサイトを5月初旬から2つ動かすようになってから、それから3回くらいサイトがダウンしました。サイト1つのときはサーバがダウンすることはほとんどなかったのですが、2つにすると調子が少し悪くなる感じがします。lighttpdの設定が甘くてメモリーを使い切ったのか、xmlrpc.phpへのPost攻撃か、他には何でしょう?

      もう少し悪化したら原因を探し出そうかなと思います。

      サイト1つだけならたぶん大丈夫だと思います。

    • kyosuke より:

      Swapを切った状態でメモリー不足になると、Raspberry Piがフリーズする気がします。もともとメモリーをたくさん使っていたのですが、最近Pythonのプログラムをループで長時間動かしたのが、サーバーが落ちる最後の一押しになっている可能性が非常に高いです。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください