# 失败使人成长

自从购入树莓派,已经被我用坏了两张MicroSD卡。

树莓派总是在我意想不到的时候停止响应,SSH访问时抛出无力的No route to host错误。当我愤怒地拔掉电源,准备重启时,却发现再也开不了机——文件系统损坏。依照网络上修复存储介质的方法,使用fsck命令无果,格式化后,当我辛辛苦苦重新安装上所有软件,准备重启,却发现又发生了掉盘,根本无法重启——这张卡算是报废了。

# 正确地重启树莓派

不是说一张SD卡值多少钱,而是在重新刷入系统后,又需要大量的时间配置新的系统,在还没有研究出怎样完全备份系统之前,正确重启树莓派,尤其是在系统不响应时正确重启树莓派,显得尤为重要。

什么是正确的关机姿势?事实上,主要问题在于,系统中的后台程序会不断进行数据存取,尤其是在使用Aria2下载的时候,直接断电会导致内存中的数据与磁盘的数据不匹配,例如一次没有完成的写入操作很可能会产生数据块的损坏。

Most common causes of file system corruption are due to improper shutdown or startup procedures, hardware failures, or NFS write errors. Shutdown should be done through one of the system shutdown commands; these sync the file system first. Never shut the system down by turning off the power. Taking a mounted file system off-line or physically write-protecting a mounted file system can also corrupt the disk. Improper startup includes not checking a file system for consistencies (fsck) before mounting it and not repairing any inconsistencies discovered by fsck. Hardware failures could be a bad block on disk, a bad disk controller, a power outage, or accidental unplugging of the system. Software errors in the kernel can also cause file system corruption.

Source: Duke Sysadmin Course

一次正确的重启意味着告诉所有应用停止运行,停止向文件系统写入,并且与文件系统同步所有还未同步的操作。要在不响应的Unix系统中做到这一点,一种显而易见的方式是让某个daemon运行重启的终端命令,另一种是使用Kernel底层的SysRq命令。

# 基于终端命令

最简单的关机命令是sudo shutdown -h nowsudo poweroff,最简单的重启命令是sudo reboot。这几项命令都是安全的,这意味着他们不会损坏文件系统。

那么要在系统不响应的情况下使用这几个命令,思路就是事先建立一个监听某些输入的后台程序,当该程序被触发,则自动运行上述的命令。

聪明的地球人已经发明出了以下一连串基于此原理的解决方案:

而我采用的就是第三种方案,因为…不需要添置任何新设备!

使用起来非常方便,首先克隆git仓库git clone https://github.com/adafruit/Adafruit-GPIO-Halt,然后进行编译:

cd Adafruit-GPIO-Halt
make
sudo make install

创建一个新的systemd service。

sudo nano /lib/systemd/system/gpio-halt.service

使用以下内容编辑service文件。

[Unit]
Description=Short pins 21 and ground to shutdown the Pi
After=multi-user.target

[Service]
Type=idle
ExecStart=/usr/local/bin/gpio-halt 21 &

[Install]
WantedBy=multi-user.target

用以下命令启动服务。

sudo systemctl daemon-reload
sudo systemctl enable gpio-halt.service
sudo systemctl start gpio-halt.service
sudo systemctl status gpio-halt.service #查看运行情况

如果你的Pi是26针,则短接GPIO7和GND,如果和我一样是40针的Pi 4B,则短接GPIO21和GND。用小钥匙碰一下,就可以轻松、安全地重启树莓派!

Pi GPIO Pins

如果你在使用我分享的温控系统,记得将温控的针脚设置为GPIO21以外的GPIO,否则风扇停转时,Pi便会重启。

# 基于SysRq

另一个方案就是使用神奇的SysRq按键(Magic SysRq Keys)是一套Linux内核能够理解的按键组合,能够帮助用户执行一系列底层操作,例如关闭所有服务、重启等。具体的按键是Alt+SysRq/PrintScr+功能键,在按下功能键时另两个按键不能松开。

SysRq的使用前提有二:

  1. Kernel仍在运行
  2. 能够连接键盘

一个常见的SysRq使用场景就是安全地重启不响应的Unix系统。这一系列按键组合被称为REISUB,也就是按照顺序使用这六个功能键,达到安全重启的目的。

  • unRaw,从X(图形界面)处取回键盘的控制权
  • tErminate,向所有进程发送SIGTERM,以让他们安全地停止运行
  • kIll,向除了init的所有进程发送SIGKILL,强制关闭还没有关闭的进程
  • Sync,将内存数据与文件系统同步
  • Unmount,安全卸载文件系统
  • reBoot,重启系统

连接键盘依次按下组合键,同样可以达到安全重启的目的。

# 数据无价

数据无价,且用且珍惜。