Raspberry PiでPythonスクリプトがクラッシュするのを防ぐためにシェルスクリプトを作成したいと思います。このPythonスクリプトは再起動時に自動的に起動されますが、時には実行中にクラッシュします。
私の現在のシェルスクリプトは次のとおりです。
#!/bin/sh
COMMAND='python home/pi/projects/mypythonscript.py'
LOGFILE=restart.txt
writelog() {
now=`date`
echo "$now $*" >> $LOGFILE
}
writelog "Starting"
while true ; do
$COMMAND
writelog "Exited with status $?"
writelog "Restarting"
done
このシェルスクリプトを使用して、2つの別々のスクリプトがクラッシュするのを防ぐために2つのコマンドラインを作成できるかどうかを尋ねたいと思います。それとも、2番目のPythonスクリプト用の新しいシェルスクリプトファイルを作成する必要がありますか?
次のように修正しようとしています。
#!/bin/sh
COMMAND1='python home/pi/projects/mypythonscript1.py'
COMMAND2='python home/pi/projects/mypythonscript2.py'
LOGFILE=restart.txt
writelog() {
now=`date`
echo "$now $*" >> $LOGFILE
}
writelog "Starting"
while true ; do
$COMMAND1
$COMMAND2
writelog "Exited with status $?"
writelog "Restarting"
done
この修正は効果がありますか?私はLinux(debian)プラットフォームに初めて接する人なので、アドバイスをいただきありがとうございます。
答え1
systemdを使用している場合は、各コマンドのサービスを作成し、システムがクラッシュしたときにそれを再起動させることができます。
それは次のとおりです。
[Unit]
Description='description of script'
[Service]
ExecStart=/path/too/script
Restart=always
[Install]
WantedBy=multi-user.target
その後、それを挿入して/etc/systemd/system
実行してsystemctl daemon-reload
サービスを開始できます。再起動後も起動します。
答え2
1 つの制御スクリプトで複数の非同期プロセスを処理する場合は、次の方法を使用できます。
#!/bin/sh
COMMAND1=(python home/pi/projects/mypythonscript1.py)
COMMAND2=(python home/pi/projects/mypythonscript2.py)
︙
rm -f COMMAND1_failed; ("${COMMAND1[@]}"; touch COMMAND1_failed)&
rm -f COMMAND2_failed; ("${COMMAND2[@]}"; touch COMMAND2_failed)&
︙
while true
do
if [ -e COMMAND1_failed ]
then
# Restart Command1
rm -f COMMAND1_failed; ("${COMMAND1[@]}"; touch COMMAND1_failed)&
fi
if [ -e COMMAND2_failed ]
then
# Restart Command2
rm -f COMMAND2_failed; ("${COMMAND2[@]}"; touch COMMAND2_failed)&
fi
︙
sleep 60
done
COMMAND1=(python home/pi/projects/mypythonscript1.py)
COMMAND1
配列として定義されます。これにより、コマンドにスペースを含む単語を含めることができますCOMMAND1=(python "home/pi/projects/my python script1.py")
。"${COMMAND1[@]}"
使用するのと似ています$COMMAND1
。最初のコマンドを実行し、そのコンポーネントを引用します。(commandA; commandB)
デフォルトでは、一時的な2行のスクリプトを作成します。コマンドA コマンドB
したがって、("${COMMAND1[@]}"; touch COMMAND1_failed)
「コマンド#1を実行して完了するまで待ってから」というファイルをタッチ(生成)しますCOMMAND1_failed
。ミニスクリプト全体がバックグラウンドで実行されるため、デフォルトスクリプトはコマンド#2などを実行し続けることができます。failed
実際には、ファイルのフルパス名を使用する必要があり、その名前を変数に入力する必要があります。- すべてのバックグラウンド操作を開始した後、デフォルトのスクリプトは無限(永久に)ループに入ります。ファイルが存在する場合は、
COMMAND1_failed
コマンド#1を再起動する必要があります。など。 sleep
必要に応じて調整してください。値が低すぎると、制御スクリプトが頻繁に実行され、システムのパフォーマンスに影響を与える可能性があります。値が高すぎると、非同期操作はタイムリーに再開されないため、システムの応答性が影響を受けます。
上記はすべてのプロセスを開始し、無限ループに入ります。これは簡単な最適化です。
#!/bin/sh
︙
touch COMMAND1_failed
︙
while true
do
if [ -e COMMAND1_failed ]
then
# (Re)start Command1
rm -f COMMAND1_failed; ("${COMMAND1[@]}"; touch COMMAND1_failed)&
fi
︙
sleep 60
done
プロセスを再起動する必要があるように見えるように必要なすべてのファイルを作成したら、ループの最初の繰り返しでバックグラウンドプロセスを開始します。唯一の違いは、プロセスを2回起動するのではなく、1回だけ起動するようにコマンドを一覧表示することです。COMMANDn_failed
また見なさい: