Skip to main content
gpio wfi has been implemented (thanks CodenameLambda)
Source Link
Gilles 'SO- stop being evil'
  • 866.1k
  • 205
  • 1.8k
  • 2.3k

Analysis and modern solution

The script is a busy loop: it keeps reading the GPIO pins over and over. It doesn't consume much memory but it keeps the CPU busy.

You should set the GPIO pin in edge mode. The WiringPi author is considering adding a wait command to thegpio utility has a gpiowfi utility but currently there is no way(wait for interrupt) command which you can use to react to an edge trigger from a shell script. (gpio wfi didn't exist back when the question was asked.)

set -e
gpio mode 0 in
gpio wfi 0 rising
echo password | sudo -S reboot

A Python solution

There is a Python library for GPIO access, which supports edge mode. Here's some completely untested Python code that should do what you want.

#!/usr/bin/env python
import os
from RPi import GPIO
GPIO.wait_for_edge(0, GPIO.RISING)
system("sudo reboot")

Additional shell tips

(true) could be written just true. The parentheses create a subprocess, which is completely unnecessary.

`gpio read 0` should be in double quotes. Without quotes, the output of the command is treated as a list of file name wildcard patterns. With double quotes, the output of the command is treated as a string. Always put double quotes around command substitutions and variable substitutions: "$(some_command)", "$some_variable". Also, you should use the syntax $(…) rather than `…`: it has exactly the same meaning, but the backquote syntax has some parsing quirks when the command is complex. Thus: if [ "$(gpio read 0)" -eq 1 ]

Don't put the root password in the script. If the script is running as root, you don't need sudo at all. If the script isn't running as root, then give the user running the script the permission to run sudo reboot without supplying a password. Run visudo and add the following line:

userwhorunsthescript ALL = (root) NOPASSWD: /sbin/reboot ""

Note that if there's an entry for the same user in the sudoers file that requires a password, the NOPASSWD entry must come after.

Once you trigger a reboot, you don't need to break the loop, the system will stop anyway.

If you decide to keep using this shell script, and your version of gpio is too old to have the wfi subcommand, here's an improved version which only checks the button state every second. Note that since the pin is only read once per second, this means you need to keep the button pressed for at least one second to be sure that the event is picked up.

gpio mode 0 in
while sleep 1; do
    if [ "$(gpio read 0)" -eq 1 ]; then
        reboot
    fi
done &

Analysis

The script is a busy loop: it keeps reading the GPIO pins over and over. It doesn't consume much memory but it keeps the CPU busy.

You should set the GPIO pin in edge mode. The WiringPi author is considering adding a wait command to the gpio utility but currently there is no way to react to an edge trigger from a shell script.

A Python solution

There is a Python library for GPIO access, which supports edge mode. Here's some completely untested Python code that should do what you want.

#!/usr/bin/env python
import os
from RPi import GPIO
GPIO.wait_for_edge(0, GPIO.RISING)
system("sudo reboot")

Additional shell tips

(true) could be written just true. The parentheses create a subprocess, which is completely unnecessary.

`gpio read 0` should be in double quotes. Without quotes, the output of the command is treated as a list of file name wildcard patterns. With double quotes, the output of the command is treated as a string. Always put double quotes around command substitutions and variable substitutions: "$(some_command)", "$some_variable". Also, you should use the syntax $(…) rather than `…`: it has exactly the same meaning, but the backquote syntax has some parsing quirks when the command is complex. Thus: if [ "$(gpio read 0)" -eq 1 ]

Don't put the root password in the script. If the script is running as root, you don't need sudo at all. If the script isn't running as root, then give the user running the script the permission to run sudo reboot without supplying a password. Run visudo and add the following line:

userwhorunsthescript ALL = (root) NOPASSWD: /sbin/reboot ""

Note that if there's an entry for the same user in the sudoers file that requires a password, the NOPASSWD entry must come after.

Once you trigger a reboot, you don't need to break the loop, the system will stop anyway.

If you decide to keep using this shell script, here's an improved version which only checks the button state every second. Note that since the pin is only read once per second, this means you need to keep the button pressed for at least one second to be sure that the event is picked up.

gpio mode 0 in
while sleep 1; do
    if [ "$(gpio read 0)" -eq 1 ]; then
        reboot
    fi
done &

Analysis and modern solution

The script is a busy loop: it keeps reading the GPIO pins over and over. It doesn't consume much memory but it keeps the CPU busy.

You should set the GPIO pin in edge mode. The gpio utility has a wfi (wait for interrupt) command which you can use to react to an edge trigger. (gpio wfi didn't exist back when the question was asked.)

set -e
gpio mode 0 in
gpio wfi 0 rising
echo password | sudo -S reboot

A Python solution

There is a Python library for GPIO access, which supports edge mode. Here's some completely untested Python code that should do what you want.

#!/usr/bin/env python
import os
from RPi import GPIO
GPIO.wait_for_edge(0, GPIO.RISING)
system("sudo reboot")

Additional shell tips

(true) could be written just true. The parentheses create a subprocess, which is completely unnecessary.

`gpio read 0` should be in double quotes. Without quotes, the output of the command is treated as a list of file name wildcard patterns. With double quotes, the output of the command is treated as a string. Always put double quotes around command substitutions and variable substitutions: "$(some_command)", "$some_variable". Also, you should use the syntax $(…) rather than `…`: it has exactly the same meaning, but the backquote syntax has some parsing quirks when the command is complex. Thus: if [ "$(gpio read 0)" -eq 1 ]

Don't put the root password in the script. If the script is running as root, you don't need sudo at all. If the script isn't running as root, then give the user running the script the permission to run sudo reboot without supplying a password. Run visudo and add the following line:

userwhorunsthescript ALL = (root) NOPASSWD: /sbin/reboot ""

Note that if there's an entry for the same user in the sudoers file that requires a password, the NOPASSWD entry must come after.

Once you trigger a reboot, you don't need to break the loop, the system will stop anyway.

If you decide to keep using this shell script, and your version of gpio is too old to have the wfi subcommand, here's an improved version which only checks the button state every second. Note that since the pin is only read once per second, this means you need to keep the button pressed for at least one second to be sure that the event is picked up.

gpio mode 0 in
while sleep 1; do
    if [ "$(gpio read 0)" -eq 1 ]; then
        reboot
    fi
done &
Source Link
Gilles 'SO- stop being evil'
  • 866.1k
  • 205
  • 1.8k
  • 2.3k

Analysis

The script is a busy loop: it keeps reading the GPIO pins over and over. It doesn't consume much memory but it keeps the CPU busy.

You should set the GPIO pin in edge mode. The WiringPi author is considering adding a wait command to the gpio utility but currently there is no way to react to an edge trigger from a shell script.

A Python solution

There is a Python library for GPIO access, which supports edge mode. Here's some completely untested Python code that should do what you want.

#!/usr/bin/env python
import os
from RPi import GPIO
GPIO.wait_for_edge(0, GPIO.RISING)
system("sudo reboot")

Additional shell tips

(true) could be written just true. The parentheses create a subprocess, which is completely unnecessary.

`gpio read 0` should be in double quotes. Without quotes, the output of the command is treated as a list of file name wildcard patterns. With double quotes, the output of the command is treated as a string. Always put double quotes around command substitutions and variable substitutions: "$(some_command)", "$some_variable". Also, you should use the syntax $(…) rather than `…`: it has exactly the same meaning, but the backquote syntax has some parsing quirks when the command is complex. Thus: if [ "$(gpio read 0)" -eq 1 ]

Don't put the root password in the script. If the script is running as root, you don't need sudo at all. If the script isn't running as root, then give the user running the script the permission to run sudo reboot without supplying a password. Run visudo and add the following line:

userwhorunsthescript ALL = (root) NOPASSWD: /sbin/reboot ""

Note that if there's an entry for the same user in the sudoers file that requires a password, the NOPASSWD entry must come after.

Once you trigger a reboot, you don't need to break the loop, the system will stop anyway.

If you decide to keep using this shell script, here's an improved version which only checks the button state every second. Note that since the pin is only read once per second, this means you need to keep the button pressed for at least one second to be sure that the event is picked up.

gpio mode 0 in
while sleep 1; do
    if [ "$(gpio read 0)" -eq 1 ]; then
        reboot
    fi
done &