파이썬에서 데몬을 어떻게 만드나요?


244

Google에서 검색하면 x2 코드 스 니펫이 나타납니다. 첫 번째 결과는 이 코드 레시피에 관한 것인데, 이 코드 레시피 는 아래에 유용한 토론과 함께 많은 문서와 설명이 있습니다.

그러나 다른 문서에는 많은 문서가 포함되어 있지 않지만 시작, 중지 및 다시 시작과 같은 명령을 전달하기위한 샘플 코드가 포함되어 있습니다. 또한 데몬이 이미 실행 중인지 확인하는 데 유용한 PID 파일을 만듭니다.

이 샘플은 모두 데몬을 만드는 방법을 설명합니다. 고려해야 할 추가 사항이 있습니까? 한 샘플이 다른 샘플보다 낫습니까? 왜 그렇습니까?


1
나는 항상 데몬 코드가 필요하지 않다는 것을 알았습니다. 왜 쉘이 그렇게하지 못하게합니까?
emil.p.stanchev

17
setsid 또는 setpgrp를 수행하지 않기 때문입니다.
bmargulies

4
supervisord.org를 사용하십시오 . 이렇게하면 stdin / stderr을 fork ()하거나 리디렉션 할 필요가 없습니다. 정상적인 프로그램을 작성하십시오.
guettli

답변:


169

현재 솔루션

PEP 3143 (표준 데몬 프로세스 라이브러리) 의 참조 구현을 python-daemon으로 사용할 수 있습니다 .

역사적 답변

Sander Marechal의 코드 샘플 은 원래 2004 년에 게시 된 원본보다 우수합니다. Pyro의 데몬 타이 저에 기여한 적이 있었지만 Sander의 코드를 사용해야 할 것입니다.


72
편집 : 원래이 회신을 게시 했으므로 이제 PEP 3143의 참조 구현을 사용할 수 있습니다. pypi.python.org/pypi/python-daemon
Jeff Bauer

@JeffBauer Original 링크가 죽었습니다. 유용하다고 생각합니다. 라이브 링크를 알지 못할 것입니까?
CrazyCasta

1
@CrazyCasta : Sander Marechal의 버전은 Wayback Machine
Jeff Bauer

1
@JeffBauer : Sander의 코드는 여전히 http://pypi.python.org/pypi/python-daemon. 더 듬직 해요. 한 가지 예 : 큰 못생긴 오류로 동일한 데몬을 두 번 시작 하십시오 python-daemon. 샌더의 코드로 : "데몬은 이미 실행 중입니다."
Basj

2
"python-daemon"모듈 문서가 여전히 누락되어 있고 (많은 다른 SO 질문도 참조) 다소 모호합니다 (이 모듈을 사용하여 명령 행에서 데몬을 올바르게 시작 / 중지하는 방법은 무엇입니까?). quit()데몬이 중지되기 전에 실행되는 메소드. 여기있어.
Basj

163

잘 작동하는 데몬 프로세스 가 될 때주의 해야사항많이 있습니다 .

  • 코어 덤프 방지 (많은 데몬이 루트로 실행되며 코어 덤프에는 중요한 정보가 포함될 수 있음)

  • chrootgaol 안에서 올바르게 행동하다

  • 사용 사례에 맞게 UID, GID, 작업 디렉토리, umask 및 기타 프로세스 매개 변수 설정

  • 승계 suid, sgid특권 포기

  • 사용 사례에 따라 제외 된 모든 열린 파일 디스크립터를 닫습니다.

  • 이미 분리 된 컨텍스트 내에서 시작하는 경우, 제대로 동작 등 init, inetd

  • 현명한 데몬 동작에 대한 신호 처리기를 설정하고 사용 사례에 따라 결정된 특정 처리기를 사용합니다.

  • 표준 스트림을 리디렉션하는 것은 stdin, stdout, stderr데몬 프로세스는 더 이상 제어 단자가 없기 때문에

  • PID 파일을 협력 적 자문 잠금으로 처리합니다.이 잠금은 많은 모순적이지만 유효한 동작 방식을 가진 웜 자체 입니다.

  • 프로세스가 종료 될 때 적절한 정리 허용

  • 실제로 좀비이어지지 않고 데몬 프로세스가됩니다.

표준 유닉스 문헌 ( UNIX 환경의 고급 프로그래밍 , W. Richard Stevens, Addison-Wesley, 1992)에 설명 된대로 이들 중 일부는 표준 입니다. 이러한 스트림 재와 같은 다른, PID 파일 처리는 ,있는 기존의 행동에 대부분의 데몬 사용자가 기대하는 것하지만 덜 표준화되어있다.

이 모든 것들은 PEP 3143 “표준 데몬 프로세스 라이브러리”사양에서 다룹니다 . 파이썬 데몬 참조 구현은 이상 파이썬 2.7에서 작동하고, 나중에 파이썬 3.2.


26
그 W. 리처드 스티븐스 :-) 그것을 철자하는 방법이기 때문에 "감옥은"올바르게 입력
bignose

7
Gaol은 영어입니다 . 포스터는 호주 출신이므로 의미가 있습니다.
devin November

1
py3k 친화적 인 버전을 만들 계획이 있습니까?
Tim Tisdall

97

다음은 새로운 데몬 응용 프로그램을 개발할 때 시작하는 기본 'Howdy World'Python 데몬입니다.

#!/usr/bin/python
import time
from daemon import runner

class App():
    def __init__(self):
        self.stdin_path = '/dev/null'
        self.stdout_path = '/dev/tty'
        self.stderr_path = '/dev/tty'
        self.pidfile_path =  '/tmp/foo.pid'
        self.pidfile_timeout = 5
    def run(self):
        while True:
            print("Howdy!  Gig'em!  Whoop!")
            time.sleep(10)

app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()

python-daemon라이브러리 가 필요합니다 . 다음을 통해 설치할 수 있습니다.

pip install python-daemon

그런 다음로 시작하고로 ./howdy.py start중지하십시오 ./howdy.py stop.


5
daemon가져올 모듈은 파이썬 (아직)의 표준에 포함되지 않습니다. 함께 설치 pip install python-daemon하거나 이와 동등 하게 설치해야합니다 .
Nate

6
당신이 설명 된 바와 같이 나는 파이썬 데몬을 설치,하지만 난 (마지막 3 개 라인과 동일) 내 응용 프로그램을 실행하려고 할 때, 나는 ImportError를 얻을 : 수 가져 오지 이름 러너
Nostradamnit

제대로 설치되었는지 확인할 수 있습니까? dpkg -L 파이썬-데몬 | grep runner /usr/share/pyshared/daemon/runner.py
Dustin Kirkland

4
이 제안은 더 이상 사용되지 않는 것 같습니다. 2013 년 9 월 현재, python.org/dev/peps/pep-3143 은 가져올 수있는 "러너"에 대해서는 언급하지 않습니다. 이것은 물론 @Nostradamnit의 관찰을 설명 할 것입니다.
offby1

2
이것은 2013 년 9 월 우분투 13.04에서 기본 Python 패키지, python2.7 및 python-daemon이 설치된 상태에서 여전히 잘 작동합니다. 그러나 python3을 사용하면 "데몬 가져 오기 러너 ImportError : 'daemon'이라는 모듈이 없습니다"라는 오류가 표시됩니다.
Dustin Kirkland

42

노트 파이썬 데몬 상자에서 데몬 뒤에 많은 문제를 해결 패키지를.

다른 기능들 중에서도 데비안 패키지 설명에서 가능합니다 :

  • 프로세스를 자체 프로세스 그룹으로 분리하십시오.
  • chroot 내에서 실행하기에 적합한 프로세스 환경을 설정하십시오.
  • suid 및 sgid 권한을 포기하십시오.
  • 열려있는 모든 파일 설명자를 닫습니다.
  • 작업 디렉토리, uid, gid 및 umask를 변경하십시오.
  • 적절한 신호 처리기를 설정하십시오.
  • stdin, stdout 및 stderr에 대한 새 파일 디스크립터를여십시오.
  • 지정된 PID 잠금 파일을 관리하십시오.
  • 종료 처리를위한 정리 기능을 등록하십시오.

35

대안-일반적인 비 데몬 (non-demonized) 파이썬 프로그램을 생성 한 다음 supervisord를 사용하여 외부 적으로 데몬을 초기화하십시오 . 이것은 많은 두통을 줄여 줄 수 있으며 * nix 및 언어 이식이 가능합니다.


1
이것이 최선의 방법이라고 생각합니다. 특히 하나의 운영 체제에서 여러 데몬을 실행하려는 경우. 코딩하지 말고 재사용하십시오.
guettli

많은 문제를 단순화합니다. 나는 진정한 데몬을 작성했다-쉽지 않다.
Chris Johnson

1
가장 좋은 답변은 여기에 숨겨져 있습니다 :)
kawing-chiu

1
이것은 금입니다. python-daemon을 실행하는 데 몇 시간을 보낸 후에 이것은 즉시 사용할 수있는 기본 솔루션입니다. 훌륭한 문서와 예제를 통해 몇 분 안에 데몬을 시작했습니다.
Nikhil Sahu

17

아마도 질문에 대한 직접적인 대답은 아니지만 systemd를 사용하여 응용 프로그램을 데몬으로 실행할 수 있습니다. 예를 들면 다음과 같습니다.

[Unit]
Description=Python daemon
After=syslog.target
After=network.target

[Service]
Type=simple
User=<run as user>
Group=<run as group group>
ExecStart=/usr/bin/python <python script home>/script.py

# Give the script some time to startup
TimeoutSec=300

[Install]
WantedBy=multi-user.target

많은 작업이 완료되었으므로 데몬 스크립트가 나머지 시스템과 유사하게 작동하기 때문에이 방법을 선호합니다.

오비


이것은 적절하고 제정신입니다. 1) /etc/systemd/system/control.service에 저장해야합니다. 2) 관리 sudosystemctl start control.service
jimper

7

YapDi 는 해커 뉴스에 나타나는 비교적 새로운 파이썬 모듈입니다. 꽤 유용하게 보입니다. 스크립트 내부에서 파이썬 스크립트를 데몬 모드로 변환하는 데 사용할 수 있습니다.


6

python-daemon은 아직 python 3.x를 지원하지 않기 때문에 메일 링리스트에서 읽을 수있는 내용에서 PEP 3143의 새로운 구현을 작성하지는 않을 것입니다 : pep3143daemon

pep3143 데몬은 적어도 파이썬 2.6, 2.7 및 3.x를 지원해야합니다.

PidFile 클래스도 포함합니다.

라이브러리는 표준 라이브러리와 6 개의 모듈에만 의존합니다.

python-daemon의 대체품으로 사용할 수 있습니다.

여기 문서가 있습니다.


6

이 함수는 응용 프로그램을 데몬으로 변환합니다.

import sys
import os

def daemonize():
    try:
        pid = os.fork()
        if pid > 0:
            # exit first parent
            sys.exit(0)
    except OSError as err:
        sys.stderr.write('_Fork #1 failed: {0}\n'.format(err))
        sys.exit(1)
    # decouple from parent environment
    os.chdir('/')
    os.setsid()
    os.umask(0)
    # do second fork
    try:
        pid = os.fork()
        if pid > 0:
            # exit from second parent
            sys.exit(0)
    except OSError as err:
        sys.stderr.write('_Fork #2 failed: {0}\n'.format(err))
        sys.exit(1)
    # redirect standard file descriptors
    sys.stdout.flush()
    sys.stderr.flush()
    si = open(os.devnull, 'r')
    so = open(os.devnull, 'w')
    se = open(os.devnull, 'w')
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())

5

@Dustin이 언급 한 데몬 모듈이 작동하지 않을까 걱정됩니다. 대신 python-daemon을 설치 하고 다음 코드를 사용했습니다.

# filename myDaemon.py
import sys
import daemon
sys.path.append('/home/ubuntu/samplemodule') # till __init__.py
from samplemodule import moduleclass 

with daemon.DaemonContext():
    moduleclass.do_running() # I have do_running() function and whatever I was doing in __main__() in module.py I copied in it.

달리기는 쉽다

> python myDaemon.py

완성도를 위해 여기 샘플 모듈 디렉토리 내용이 있습니다.

>ls samplemodule
__init__.py __init__.pyc moduleclass.py

moduleclass.py의 내용은

class moduleclass():
    ...

def do_running():
    m = moduleclass()
    # do whatever daemon is required to do.

2

파이썬에서 데몬을 사용할 때 고려해야 할 사항이 하나 더 있습니다.

파이썬 로깅 을 사용하고 있으며 데몬 화 후 계속 사용 close()하려면 처리기 (특히 파일 처리기) 를 호출해야합니다 .

이 작업을 수행하지 않으면 처리기는 여전히 파일이 열려 있다고 생각할 수 있으며 메시지는 단순히 사라집니다. 즉, 로거가 파일이 닫 혔음을 알 수 있습니다.

이것은 데몬을 사용할 때 열려있는 모든 파일 설명자를 무차별 적으로 닫는 것으로 가정합니다. 대신 로그 파일을 제외한 모든 파일을 닫으려고 시도 할 수 있습니다 (그러나 일반적으로 모든 것을 닫은 다음 원하는 것을 다시 여는 것이 더 간단합니다).


예를 들어 DaemonContext의 files_preserve 옵션을 사용하여 로깅 처리기를 데몬에 전달하는 것보다 새로운 로깅 처리기를 여는 것이 더 낫다고 생각하십니까?
HeyWatch 이것은

로거를 닫는 것만으로 새로운 로거를 만들지 않습니다 (필요할 때 다시 열 것입니다). 그러나 실제로 그렇게하기는 쉽지만, 다른 영리한 일을하고 있기 때문에 DaemonContext를 사용하는 것이 좋습니다.
Matthew Wilcoxson

2

python-daemon 모듈이 제공하는 순수한 Python 솔루션을 선호 할 수도 있지만 적어도 BSDLinux 에는 올바른 daemon(3)기능을 수행 하는 기능이 있습니다.libc

파이썬에서 호출하는 것은 쉽습니다.

import ctypes

ctypes.CDLL(None).daemon(0, 0) # Read the man-page for the arguments' meanings

남은 것은 PID 파일의 생성 및 잠금뿐입니다. 그러나 당신은 자신을 다룰 수 있습니다 ...


1

데몬이 멈추기 전에 실행 되는 메소드 를 추가하기 위해 Sander Marechal의 코드 샘플에서 몇 줄을 수정했습니다 ( 허용 된 답변의 @JeffBauer에 의해 언급 됨 ) quit(). 이것은 때때로 매우 유용합니다.

여기있어.

참고 : "python-daemon"모듈을 사용하지 않습니다 (문서가 여전히 누락되어 있고 (다른 많은 SO 질문도 참조)) 다소 모호합니다 (이 모듈을 사용하여 명령 행에서 데몬을 올바르게 시작 / 중지하는 방법)?


-1

몇 년 동안 많은 시도 (여기에서 주어진 모든 대답을 시도했지만 모두 끝에 작은 단점이 있음), 이제 파이썬에서 직접 데몬을 시작, 중지, 다시 시작하는 것보다 더 좋은 방법이 있음을 알았습니다. : 대신 OS 도구를 사용하십시오.

예를 들어, 리눅스, 대신 일을 python myapp start하고 python myapp stop, 나는 응용 프로그램을 시작하려면 다음을 수행하십시오

screen -S myapp python myapp.py    
CTRL+A, D to detach

또는 하나의 명령screen -dmS myapp python myapp.py 으로 시작하고 분리합니다 .

그때:

screen -r myapp

이 터미널에 다시 연결하십시오. 터미널에 들어가면 Ctrl + C를 사용하여 중지 할 수 있습니다.


-2

Python으로 데몬을 만드는 가장 쉬운 방법은 Twisted 이벤트 중심 프레임 워크 를 사용하는 것 입니다. 데몬 화에 필요한 모든 것을 처리합니다. 리액터 패턴 을 사용하여 동시 요청을 처리합니다.


5
사용하기에는 너무 큰 망치입니다. 대부분의 사람들은 단지 데몬으로 작성한 짧은 Python 스크립트를 실행하기를 원합니다. 위에 설명 된대로 python-daemon이 정답입니다.
Tom Swirly

2
이 답변은 거만했지만 유용했습니다.
fiatjaf

-28

시간의 80 %가 사람들이 "데몬"이라고 말하면 서버 만 원합니다. 이 시점에서 질문이 명확하지 않기 때문에 가능한 답변 영역이 무엇인지 말하기 어렵습니다. 서버가 충분하므로 시작하십시오. 실제 "데몬"이 실제로 필요한 경우 (드문 경우) nohup서버를 데몬 화 하는 방법으로 읽어보십시오 .

실제 데몬이 필요할 때까지 간단한 서버를 작성하십시오.

또한 WSGI 참조 구현 도 살펴보십시오 .

또한보고 간단한 HTTP 서버 .

"고려해야 할 추가 사항이 있습니까?"예. 약 백만 가지. 어떤 프로토콜? 몇 건의 요청이 있습니까? 각 요청을 처리하는 데 얼마나 걸립니까? 얼마나 자주 도착합니까? 전용 프로세스를 사용 하시겠습니까? 실? 하위 프로세스? 데몬을 작성하는 것은 큰 일입니다.


12
이 라이브러리들 중 어느 것도 fork()두 개는 물론 단일도하지 않습니다 . 데몬 화와는 아무런 관련이 없습니다.
Brandon Rhodes

8
유닉스 운영 체제에서 "데몬"이라고하는 공중 전화 교환 원과 같은 "데몬"프로세스는 "측면에서는"프로세스입니다. 대신 직접 사용자의 TTY를 통해 단일 사용자 봉사, 데몬이없는 TTY에 속하지만 시스템에 많은 사용자의 요청에 응답 할 수 있습니다, 또는 - 같은 crond또는 syslogd- 전체 시스템 하우스 키핑 서비스를 수행합니다. 데몬 프로세스를 만들려면 fork()시스템 콘솔을 포함하여 모든 제어 터미널의 신호에 영향을받지 않도록 최소한 모든 파일 디스크립터를 닫은 상태에서 이중 을 수행해야합니다 . bignose의 답변을 참조하십시오.
Brandon Rhodes

5
@S Lott — "서버"는 프로세스 가 수행 하는 작업을 설명 합니다 (자체 작업을 시작하는 대신 들어오는 요청을 청취 함). “데몬”은 프로세스 가 실행되는 방법을 설명합니다 (창 또는 제어 터미널없이). SimpleHTTPServer실제로 서버이지만 자체적으로 데몬을 만드는 방법을 모르는 서버입니다 (예 : Ctrl-C). nohup당신의 nohupped 서버가 실제로 그래서 - 순진 과정을 디먼 화 할 수있는 유틸리티입니다 모두 데몬 당신이 주장대로 정확하게 서버. 이 스택 오버플로 질문은 본질적으로 " nohup파이썬에서 어떻게 구현할 수 있습니까?"
Brandon Rhodes

5
그렇습니다.하지만 OPs 질문에 대한 나의 이해는 파이썬 프로그램 내에서 다른 것을 사용하지 않고 디먼 화를하고 싶다는 것입니다.
Noufal Ibrahim

4
@S 로트 — 감동 할 필요가 없습니다! 다른 모든 답변의 저자는“데몬”이 무엇을 의미하는지 알았으므로이 질문을 해석하는 능력은 독특하지 않습니다. :) 그리고 저자가 바퀴를 다시 발명하기를 원한다는 생각을 어디서 얻었습니까? 나는 nohup훌륭한 도구 라고 생각 하며, 유용한 아이디어를 실제 답변으로 옮기면 -1 표를 제거합니다. 실제로, 당신이 언급 supervisord하고 그것이 어떻게 시작, 스크립트를 시작하고 스로틀 링을 다시 시작하지 않아도 저자가 어떻게 저장 하는지를 알게된다면, 나는 당신을 +1 할 것입니다. :)
Brandon Rhodes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.