
ボタンを1つだけ押すと、Raspberry Piを再起動するミニスクリプトが作成されました。スクリプトは WiringPi (gpio コマンド) を使用してピン 0 (Raspberry Pi 標準番号付けシーケンスのピン 17) を入力に設定してから、1 になるまで (つまり、ボタンを押したり押したりしているとき) 値を読み取ります。
これは私のスクリプトです。
gpio mode 0 in
while (true)
do
if [ `gpio read 0` -eq 1 ]
then
echo password | sudo -S reboot
break
fi
done &
スクリプトがうまく実行され、すべてがうまくいきます。
しかし、Piに慣れていない人のために、私は私が使っていたループで簡単に消費されるのに非常に限られたハードウェアリソース(512 MBのRAMを含む)が付属しています。
ここで私が達成しようとしているのは、無条件ループのようなものを提供する必要0
なしに値が から に変わる時期を bash が調べる別の方法を探すことです。1
これは可能ですか?あなたの考えを共有してください。
答え1
分析と最新のソリューション
スクリプトは忙しいループです。 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として実行される場合、sudoはまったく必要ありません。スクリプトがrootとして実行されない場合は、スクリプトを実行しているユーザーにsudo reboot
パスワードを指定せずに実行する権限を付与してください。visudo
次の行を実行して追加します。
userwhorunsthescript ALL = (root) NOPASSWD: /sbin/reboot ""
sudoersファイルで同じユーザーのエントリにパスワードが必要な場合は、そのエントリは後で来る必要がありNOPASSWD
ます。
再起動がトリガされると、ループを中断する必要はなく、システムはとにかく停止します。
このシェルスクリプトを引き続き使用することにしましたが、バージョンが古すぎてサブコマンドがgpio
利用できない場合は、wfi
毎秒ボタンの状態のみを確認する拡張バージョンがあります。ピンは毎秒1回だけ読み取られるので、イベントが選択されるようにするには、少なくとも1秒間ボタンを押し続ける必要があることを意味します。
gpio mode 0 in
while sleep 1; do
if [ "$(gpio read 0)" -eq 1 ]; then
reboot
fi
done &
答え2
あなたが持っているもの忙しいループ。ループはメモリをほとんど消費しませんが、多くのCPUを消費します。これは通常、sleep
ループ本体に追加することで軽減できます。
while (true)
do
if [ `gpio read 0` -eq 1 ]
then
echo passowrd | sudo -S reboot
break
fi
sleep 1
done &
忙しいサイクルから抜け出すことは、gpio
あなたが何をするかによって異なります。一部のシステムコール(例select()
:)は、ファイル記述子が準備されるまでブロックできます。
効率性の観点から、()
aroundtrue
コマンドは実際にはtrue
サブシェルで実行されます。これは必須ではなく、次の方法でよりよく表現できます。
while (( $(gpio read 0) != 1 )); do
sleep 1
done
echo passowrd | sudo -S reboot
答え3
以下を試してください。
while ! gpio read 0 ; do
sleep 1
done
echo password | sudo -S reboot