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
또한보십시오: