단일 쉘 스크립트를 사용하여 여러 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

이 쉘 스크립트를 사용하여 두 개의 별도 스크립트가 충돌하는 것을 방지할 수 있도록 두 개의 명령줄을 만들 수 있는지 묻고 싶습니다. 아니면 두 번째 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

하나의 제어 스크립트에서 여러 비동기 프로세스를 처리하려는 경우 다음 방법을 사용할 수 있습니다.

#!/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) 기본적으로 임시 두 줄 스크립트를 만듭니다.
    명령 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

프로세스를 (다시)시작해야 하는 것처럼 보이도록 필요한 모든 파일을 생성한 후 루프의 첫 번째 반복에서 백그라운드 프로세스를 시작합니다. 유일한 차이점은 프로세스를 두 번 시작하는 대신 한 번만 시작하라는 명령을 나열한다는 것입니다.COMMANDn_failed

또한보십시오:

관련 정보