単一のシェルスクリプトを使用して複数のPythonスクリプトがクラッシュするのを防ぎますか?

単一のシェルスクリプトを使用して複数のPythonスクリプトがクラッシュするのを防ぎますか?

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

また見なさい:

関連情報