Python 스크립트가 종료되거나 죽으면 자동으로 다시 시작하는 방법


31

내 우분투 컴퓨터 (12.04)의 백그라운드에서 Python 스크립트를 다음과 같이 실행하고 있습니다.

nohup python testing.py > test.out &

이제 어떤 단계에서 위의 Python script이유가 무엇이든 죽을 수도 있습니다.

그래서 cron agent어떤 이유로 든 죽이면 위의 Python 스크립트를 자동으로 다시 시작할 수있는 일종의 bash 쉘 스크립트 가 있다고 생각합니다 .

이것이 가능합니까? 그렇다면 이러한 종류의 문제를 해결하는 가장 좋은 방법은 무엇입니까?

최신 정보:

testing.conf이 같은 파일을 만든 후 -

chdir /tekooz
exec python testing.py
respawn

sudo 명령을 실행하여 시작했지만 ps ax를 사용하여 프로세스가 실행되는 것을 볼 수 없습니까?

root@bx13:/bezook# sudo start testing
testing start/running, process 27794
root@bx13:/bezook# ps ax | grep testing.py
27806 pts/3    S+     0:00 grep --color=auto testing.py

px ax가 왜 나에게 아무것도 보여주지 않는지 아십니까? 내 프로그램이 실행 중인지 어떻게 확인합니까?

이것은 내 파이썬 스크립트입니다-

#!/usr/bin/python
while True:
    print "Hello World"
    time.sleep(5)

답변:


24

Ubuntu (14.04, 16.04 이상까지 systemd 사용)에서는 cstart 작업보다 upstart를 사용하여 그렇게 할 수 있습니다. 구성 설정을 넣고 respawn/etc/init 을 지정했는지 확인하십시오.

최소한의 파일 일 수 있습니다 /etc/init/testing.conf(으로 편집 root).

chdir /your/base/directory
exec python testing.py
respawn

그리고 당신은 테스트 할 수 있습니다 /your/base/directory/testing.py:

from __future__ import print_function

import time

with open('/var/tmp/testing.log', 'a') as fp:
    print(time.time(), 'done', file=fp)
    time.sleep(3)

그리고 시작 :

sudo start testing

다음과 같이 (다른 창에서) 일어나는 일을 따르십시오.

tail -f /var/tmp/testing.log

멈춰 :

sudo stop testing

[start on][2]시스템 부팅시 명령이 시작되도록 추가 할 수도 있습니다 .


cron 작업을 사용하는 경우 강력한 PID 파일 처리를위한 코드를 구현하거나 찾을 수 있습니다. service / script / daemon이 PID 파일 (일반적으로 / var / run 아래에 있음)을 작성하고 시작 코드가 파일 내용이 오래되었는지 (살인 된 프로세스에 의해 남아 있는지) 확인하도록합니다. 이런 종류의 코드는 놀랍게도 인종과 코너 사례를 작성하기가 어렵습니다. stackoverflow.com/questions/788411/…
Jim Dennis

@Zelda : 제안 해 주셔서 감사합니다. 저는 Linux / Unix 세계에 익숙하지 않습니다. /etc/init파일 에서 어떤 유형의 변경을해야 합니까? 당신이 나를 위해 단계별 안내를 제공 할 수 있다면, 나는 무언가를 배우고 옳은 일을 할 수있을 것입니다.
arsenal

@ Webby 나는 대답을보다 완전하게 만들었습니다. 출력 할 파일을 열고 인쇄 문을 다시 쓰지 않으려면 sys.stdout = open(file_name, 'w')처음 과 같은 작업을 수행 할 수 있습니다 .
젤다

젤다 감사합니다. 도움을 주셔서 감사합니다 .. 몇 가지 세부 사항으로 질문을 업데이트했습니다 .. testing.py가 실행 중인지 확인하기 위해 이와 같이하려고합니다 px ax | grep testing.py. 나에게 아무것도 반환하지 않습니까? 왜 그런지 알아?
arsenal

모든 것을 try / except 절에 넣고 로그 파일에 어떤 예외가 생성되었고 프로그램이 종료되는지 기록해야합니다. stdout에 쓸 수 없으므로 print 문이 작동하지 않을 수 있습니다.
젤다

20

더 쉘 지향적 인 접근 방식을 취할 수도 있습니다. 당신이 cron이 죽으면 그것을 스크립트에 대한보고 및 다시 시작.

  1. 을 실행하여 새 크론 탭을 만듭니다 crontab -e. 즐겨 찾는 텍스트 편집기 창이 나타납니다.

  2. 이 파일을 방금 연 파일에 추가하십시오

    */5 * * * * pgrep -f testing.py || nohup python /home/you/scripts/testing.py > test.out
  3. 파일을 저장하고 편집기를 종료하십시오.

방금 crontab5 분마다 실행될 새 스크립트를 작성하고 스크립트가 아직 실행 중이 아니면 스크립트를 시작하십시오. 에 대한 멋진 튜토리얼을 보려면 여기 를 참조 하십시오cron . 공식 우분투 문서 cron여기에 있습니다 .

실행중인 실제 명령 pgrep은 명령 행에 제공된 문자열에 대해 실행중인 프로세스를 검색하는 것입니다. pgrep foo명명 된 프로그램을 검색 foo하고 프로세스 식별자를 반환합니다 . pgrep -f프로그램 이름뿐만 아니라 프로그램을 시작하는 데 사용되는 전체 명령 줄을 검색합니다 (파이썬 스크립트이기 때문에 유용합니다).

||기호 수단은 "이전 명령이 실패하면이 작업을 수행 할". 따라서 스크립트가 실행되고 있지 않으면 pgrep아무것도 찾지 않고 스크립트가 시작되므로 실패합니다.


고맙습니다 ..하지만 저는 리눅스와 유닉스를 처음 사용하므로 crontab이 어디에 있는지 모르십니까? 이 파일이 내 우분투 컴퓨터의 파일입니까?
arsenal

@Webby는 업데이트 된 답변을 참조하십시오.
terdon

terdon에게 감사드립니다. crontab -e내 파이썬 스크립트가있는 디렉토리 에서이 명령 을 실행할 수 있습니다 .
arsenal

1
@Webby는 원하는 곳 어디에서나 실행할 수 있습니다. cron스케줄링 데몬이며 백그라운드에서 실행되는 서비스입니다. 파이썬 스크립트가 귀하 $PATH의 디렉토리에 없으면 (어디에서나 시작할 수 없지만 디렉토리에 있어야하는 경우) 업데이트 된 답변과 같이 스크립트의 전체 경로를 사용하십시오.
terdon

감사. 방금 새 crontab을 만들고 동일한 단일 행을 추가하여 1 분 동안 파일을 편집했습니다. 이미 True. testing.py라는 이름으로 돌아가는 Hello World Python 스크립트를 이미 만들었습니다. crontab 파일에서 1 분 후에 자동으로 testing.py를 시작해야합니까? 그런 다음 1 분마다 파이썬 스크립트가 실행 중인지 계속 확인합니까? 그렇다면 crontab -e 파일을 저장 한 후 ps ax | grep testing.py 그리고 나는 그 어떤 프로세스도 볼 수 없습니까?
arsenal

6

명령 줄 옵션을 사용하여 테스트 프로그램이 출력을 리디렉션하도록 한 다음 간단한 파이썬 스크립트를 사용하여 프로그램을 무기한으로 다시 시작할 수 있습니다.

import subprocess

while True:
    try:
        print subprocess.check_output(['python', 'testing.py'])
    except KeyboardInterrupt:
        break

이 프로그램을 배경에 넣을 수 있으며 일단 중지하려면 전경으로 끌어 당기면됩니다.


6

실제로 이것을 프로덕션에 사용해서는 안되지만 다음과 같이 할 수 있습니다.

#!/bin/sh

while true; do
  nohup python testing.py >> test.out
done &

어떤 이유로 든 파이썬 프로세스가 종료되면 셸 루프는 계속 진행하고 다시 시작하여 .out파일을 원하는대로 추가합니다 . 오버 헤드가 거의없고 설정 시간이 거의 없습니다.


6

UNIX / Linux에서 프로세스를 모니터하고 다시 생성하는 방법에는 여러 가지가 있습니다. 가장 오래된 것 중 하나는 이전 SysV init 시스템을 사용하는 경우 / etc / inittab의 "respawn"항목입니다. 또 다른 방법은 DJ Bernstein의 daemontools 패키지 에서 수퍼바이저 데몬을 사용하는 것 입니다. 다른 옵션은 Ubuntu upstart ... 또는 systemd 또는 다른 기능을 사용하는 것입니다.

그러나 대안 initPardus 의 Python 코드 : 특히 mudur 데몬을 볼 수 있습니다.

cron 작업 (및 PID 파일 처리)을 사용하기로 결정한 경우이 PEP 3143을 읽고 해당 참조 구현을 사용하십시오.

다른 의견에서 언급했듯이 강력한 PID 파일 처리는 까다 롭습니다. 인종과 코너 사건이 발생하기 쉽습니다. PID 파일이 NFS 또는 기타 네트워크 파일 시스템에서 종료 될 가능성이있는 경우 까다로워집니다 (일부 원 자성에서는 적절한 로컬 UNIX / Linux 파일 시스템 에서 파일 처리 의미론을 얻을 수 있음을 보장합니다 . 일부 버전 및 NFS 구현에서는, 예를 들어). 또한 UNIX에서 파일 잠금에 대한 의미는 까다로울 수 있습니다. ( 예를 들어 SIGKILL로 프로세스를 종료하는 프로세스가 종료 될 때 대상 OS에서 flock또는 fcntl잠금이 즉시 해제됩니까?).


3

ps-watcher로 monit 또는 프로세스 모니터링을 사용할 수도 있습니다

Monit은 UNIX 시스템에서 프로세스, 프로그램, 파일, 디렉토리 및 파일 시스템을 관리하고 모니터링하기위한 오픈 소스 유틸리티입니다. Monit은 자동 유지 보수 및 수리를 수행하며 오류 상황에서 의미있는 인과 관계 조치를 실행할 수 있습니다.

시나리오의 예는 다음과 같습니다.

check process myprocessname
        matching "myprocessname"
        start program = "nohup /usr/bin/python /path/testing.py > /tmp/test.out &"
        stop program = "/usr/bin/killall myprocessname"

monit 예제를 살펴보십시오


1

당신은 감독자가 필요합니다, 당신은 감독자 를 사용할 수 있습니다 . 파이썬 기반 감독자이므로 필요한 경우 쉽게 수정할 수 있습니다.

.ini 파일 구문을 가진 파일로 제어합니다.


0

Terdon의 대답 pgrep -f testing.py은 결코 실패하지 않았기 때문에 나를 위해 작동하지 않았습니다 . -f 옵션 때문에 cron 작업의 pid를 가져옵니다. 그러나 -f 옵션이 없으면 pgrep는 testing.py를 찾을 수 없으므로 testing.py라는 프로세스가 없기 때문입니다.

이것에 대한 나의 해결책은 변화하는 것이 었습니다

pgrep -f testing.py

pgrep -f testing.py | pgrep python

이것은 전체 crontab 작업은 다음과 같습니다.

*/5 * * * * pgrep -f testing.py | pgrep python || nohup python /home/you/scripts/testing.py > test.out

0

필자의 경우 빠른 수정으로 프로그램이 종료되어 오류가 발생하거나 종료되었을 때 프로그램을 계속 실행하고 싶었습니다. 반면에 프로그램이 올바르게 종료되면 실행을 중지하고 싶었습니다 (반환 코드 = 0)

Bash에서 테스트했습니다. 다른 쉘에서도 잘 작동합니다.

#!/bin/sh

echo ""
echo "Use: $0 ./instagram.py"
echo ""

echo "Executing $1 ..."

EXIT_CODE=1
(while [ $EXIT_CODE -gt 0 ]; do
    $1
    # loops on error code: greater-than 0
    EXIT_CODE=$?
done)

0

terdon의 답변을 들어, pgrep -f testing.py의 설명에 따라 거짓을 반환하지 않습니다 여기 :

문제는 cron이 명령을 실행하기 위해 쉘을 생성하고 해당 쉘의 인수는 -f를 사용하기 때문에 pgrep와 일치한다는 것입니다.

Matt의 대답 pgrep -f testing.pypgrep python실행중인 Python 스크립트와 일치하므로 쓸모가 없습니다 . 따라서 두 개의 Python 스크립트 cronjob 인 경우 두 번째 cronjob은 절대 실행되지 않습니다.

그런 다음 pgrep -f testing.py의견에서 해결 할 솔루션을 찾았습니다 : https://askubuntu.com/questions/1014559/running-pgrep-in-a-crontab?noredirect=1&lq=1

두 개의 Python 스크립트를 실행하는 내 cron :

* * * * * pgrep -f '^/usr/bin/python36 /home/ec2-user/myscript1\.py' || nohup /usr/bin/python36 /home/ec2-user/myscript1.py

0 * * * * pgrep -f '^/usr/bin/python36 /home/ec2-user/myscript2\.py' || nohup /usr/bin/python36 /home/ec2-user/myscript2.py
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.