分析和现代解决方案
该脚本是一个繁忙的循环:它不断读取GPIO引脚。它不会占用太多内存,但会使CPU繁忙。
您应该将GPIO引脚设置为边沿模式。该gpio
实用程序具有wfi
(等待中断)命令,可用于对边沿触发作出反应。(gpio wfi
问问题时不存在。)
set -e
gpio mode 0 in
gpio wfi 0 rising
echo password | sudo -S reboot
Python解决方案
有一个用于GPIO访问的Python库,它支持边缘模式。这是一些完全未经测试的Python代码,可以执行您想要的操作。
#!/usr/bin/env python
import os
from RPi import GPIO
GPIO.wait_for_edge(0, GPIO.RISING)
system("sudo reboot")
其他外壳技巧
(true)
可以写成true
。括号会创建一个子过程,这完全没有必要。
`gpio read 0`
应该用双引号引起来。不带引号的情况下,命令的输出将被视为文件名通配符模式的列表。用双引号将命令的输出视为字符串。始终在命令替换和变量替换两边加上双引号:"$(some_command)"
,"$some_variable"
。另外,您应该使用语法$(…)
而不是`…`
:它具有完全相同的含义,但是当命令复杂时,反引号语法会有一些解析问题。从而:if [ "$(gpio read 0)" -eq 1 ]
不要在脚本中输入root密码。如果脚本以root身份运行,则根本不需要sudo。如果脚本不是以root用户身份运行的,则为运行脚本的用户授予运行权限,sudo reboot
而无需提供密码。运行visudo
并添加以下行:
userwhorunsthescript ALL = (root) NOPASSWD: /sbin/reboot ""
请注意,如果sudoers文件中存在同一用户的条目,需要输入密码,则该NOPASSWD
条目必须位于后面。
触发重新启动后,无需中断循环,系统仍将停止。
如果您决定继续使用此Shell脚本,并且您的的版本gpio
太旧而无法使用wfi
子命令,则此版本为改进版本,仅每秒检查一次按钮状态。请注意,由于该引脚每秒只能读取一次,因此这意味着您需要按住按钮至少一秒钟,以确保事件被拾取。
gpio mode 0 in
while sleep 1; do
if [ "$(gpio read 0)" -eq 1 ]; then
reboot
fi
done &