Evitar que vários scripts python travem com um script de shell único?

0

Eu gostaria de criar um script de shell para evitar que um script python falhe em um Raspberry Pi. Este script python é iniciado automaticamente ao reiniciar com o cron, no entanto, às vezes, ele pode travar durante a execução.

Atualmente, meu script de shell diz:

#!/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

Eu queria perguntar se posso criar duas linhas de comando, para garantir que dois scripts independentes possam ser impedidos de travar com esse script de shell? Ou eu tenho que fazer um novo arquivo de script de shell para o segundo script python?

Estou pensando em modificá-lo desta maneira:

#!/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

Esta modificação funcionaria? Eu aprecio qualquer conselho, pois ainda sou novo na plataforma linux (debian).

    
por Craver2000 15.02.2018 / 14:20

2 respostas

2

Se você estiver usando o systemd, poderá criar um serviço para cada comando e, em seguida, obter o systemd para reiniciá-lo se ele falhar.

Algo como:

[Unit]
Description='description of script'

[Service]
ExecStart=/path/too/script
Restart=always

[Install]
WantedBy=multi-user.target

Isso pode ser colocado em /etc/systemd/system , depois de executar systemctl daemon-reload , você poderá iniciar o serviço. Ele também será iniciado após a reinicialização.

    
por 15.02.2018 / 15:05
0

Se você quiser manipular um número arbitrário de processos assíncronos de um script de controle, você pode usar essa abordagem:

#!/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
  • %código% define COMMAND1=(python home/pi/projects/mypythonscript1.py) para ser uma matriz. Isso permite que o comando inclua palavras que contenham espaços; por exemplo, algo como COMMAND1 .
  • COMMAND1=(python "home/pi/projects/my python script1.py") é análogo ao uso de "${COMMAND1[@]}" ; ele executa seu primeiro comando, citando suas palavras constituintes.
  • %código% essencialmente cria um script ad-hoc de duas linhas:
    commandA
    commandB
    então $COMMAND1 diz “Execute o comando # 1, espere que ele termine e, em seguida, toque em (criar) um arquivo chamado (commandA; commandB) . Este mini-script inteiro é executado em segundo plano, então o script principal pode continuar e executar o comando # 2, etc.
  • Realisticamente, provavelmente você deve usar caminhos completos para os arquivos ("${COMMAND1[@]}"; touch COMMAND1_failed) , e talvez colocar seus nomes em variáveis.
  • Depois de iniciar todos os trabalhos em segundo plano, o script principal insere um loop infinito (para sempre). Se o arquivo COMMAND1_failed existir, isso significa que o comando # 1 e precisa ser reiniciado. Etc.
  • Ajuste o failed conforme desejado. Valor muito baixo, e o script de controle pode ser executado com tanta frequência que afeta o desempenho do sistema. Um valor muito alto e as tarefas assíncronas não serão reiniciadas prontamente, então a capacidade de resposta do sistema sofreria dessa maneira.

O acima começa todos os processos, e depois entra em loop infinito. Aqui está uma otimização trivial:

#!/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

que inicia os processos em segundo plano na primeira iteração do loop, depois de criar todos os arquivos COMMAND1_failed necessários para fazer parecer que os processos precisam ser (re) iniciados. A única diferença é que lista os comandos para iniciar os processos uma vez em vez de duas vezes.

Veja também:

por 15.02.2018 / 20:55