树莓派用一个回形针来安全关机

刚买Zero W的时候最头疼的一件事就是如何安全关机。有好几次Zero W SSH连接不上,只能强行断电结果把系统给搞坏了。可能是磁盘还在读写,意外断电,会让磁盘丢失资料。

可惜的是Zero W短路了,我不得不上咸鱼淘了一个二手1代B型来替代它。

树莓派1B是第一代树莓派产品,只有26个引脚,和后面的几代40个引脚的都不同。虽然引脚数不同,但是只要有GPIO引脚就能够实现安全关机。具体的做法是,树莓派运行一个脚本来监视GPIO引脚,如果发现状态变化,就执行关机命令。可以用一根回形针(任何导电物品)连通两个引脚,来发出关机命令。具体可以参照这篇文章

首先下载并编译脚本,github上有开源的代码

1
2
3
4
git clone https://github.com/adafruit/Adafruit-GPIO-Halt
cd Adafruit-GPIO-Halt
make
sudo make install

接下来将编译后的gpio-halt脚本移到/usr/local/bin目录下

1
sudo mv gpio-halt /usr/local/bin

创建一个服务方便启动或关闭gpio-halt脚本,可以使用update-rc.d命令来自动创建。首先在/etc/init.d目录下创建一个gpio-halt.sh脚本文件,内容如下

1
2
#!/bin/sh
/usr/local/bin/gpio-halt 7 &

注意,上面的参数7是7号GPIO引脚的意思,如果是1B以后的树莓派,即40引脚的,应该改成21号引脚。

然后添加执行权限给gpio-halt.sh脚本文件

1
sudo chmod +x /etc/init.d/gpio-halt.sh

使用update-rc.d命令创建服务

1
sudo update-rc.d gpio-halt.sh defaults

执行上面的命令后,系统会向/run/systemd/generator.late/目录添加一个service,这样我们就可以使用sudo service gpio-halt.sh start|stop|status命令来控制脚本运行。

我之前就发现一个问题,网上说使用update-rc.d命令会自动设置脚本开机启动,但是我尝试重启了一遍后发现gpio-halt.sh脚本服务并没有自启,还是需要手动开启,问题就出在gpio-halt.sh脚本文件上。正确的写法应该参照LSBInitScripts的规范来,比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/sh
### BEGIN INIT INFO
# Provides: scriptname
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO

case "$1" in
start)
echo "start scriptname"
;;
stop)
echo "stop scriptname"
;;
restart)
echo "restart scriptname"
;;
*)
echo "Usage: $0 (start|stop)"
;;
esac
exit 0

上面的脚本我只是举个例子,没有实际的执行代码,目前还不会写。于是为了能快速实现开机自启,我在/etc/rc.local文件里添加了一行代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi

# 我新增的代码
# Short pins 7 and ground to shutdown the Pi
sudo service gpio-halt.sh start

exit 0

现在再重启一下试试,看看gpio-halt.sh服务有没有自启。如果已经启动,找一根回形针,最好接上屏幕观察一下,接通GND以及GPIO7引脚,看看是不是关机了呢?反正我是可以了。以后可以弄一个开关接GND以及GPIO7,开关按下就可以实现安全关机。

avatar

chilihotpot

You Are The JavaScript In My HTML