2010-06-01 16 views
5

Mam działający program oparty na języku Python, który chcę uruchomić jako demon. Obecnie robię to w bardzo hackerskim sposobie uruchamiania go w sesji screen-d -m name i zabijam go przy pomocy pkill -9 -f name.Jak zarządzać demonem opartym na języku Python w systemie Linux?

Ostatecznie robię to, aby przenieść to do lepszego systemu, którego używamy tutaj (w ten sposób Nie chcę modyfikować programu), ale w międzyczasie szukam czystszego sposobu na zrobienie to.

Moje bieżące myślenie jest wyzwaniem jako zadanie w tle ze skryptu inti.d, ale jak mogę napisać tę część, aby ją przywrócić?

Odpowiedz

1

Zaczynając ją z init.d stylu skryptu jest dobrym sposobem. Usuwasz go za pomocą sygnałów POSIX ... Zobacz StackOverflow, Signal handling in Python.

+0

Mogę "zabić -9" to wszystko, co mnie interesuje, ale nie wiem, jak niezawodnie znaleźć jego PID. – BCS

+0

@BCS: '-9' jest często ... * przesadą * (wybacz kalambur). Zobacz [kill -9] (http://speculation.org/garrick/kill-9.html). Jeśli chodzi o znajdowanie swojego PID, twój skrypt może utworzyć plik pidfile w '/ var/run' lub użyć biblioteki lib, która pozwala ci ustawić' argv [0] 'na pewną łatwo rozpoznawalną nazwę do użycia z' pkill'. –

6

Na Linux-ie jest narzędzie start-stop-daemon jako część narzędzi init.d.

Jest bardzo elastyczny i pozwala na różne sposoby przechwytywania pid serwera.

Istnieje również plik /etc/init.d/skeleton, który może służyć jako podstawa do własnego skryptu init.d.

Jeśli twoja platforma docelowa jest oparta na debianach, warto utworzyć pakiet debinowy, aby go wdrożyć, ponieważ pomaga również w zapewnieniu właściwego włączenia demona do reszty systemu. I nie jest to zbyt skomplikowane (jeśli robiłeś to dziesięć razy wcześniej ;-)

+0

Wygląda jak dobre rzeczy. – BCS

3

Jeśli chcesz zrobić to z kodem w pythonie, jest to dość standardowa metoda C, która została przeniesiona do pythona, którego używam. Działa bezbłędnie i można nawet wybrać wyjście pliku.

import os 
import signal 
def daemonize(workingdir='.', umask=0,outfile='/dev/null'): 
#Put in background 
pid = os.fork() 
if pid == 0: 
    #First child 
    os.setsid() 
    pid = os.fork() #fork again 
    if pid == 0: 
     os.chdir(workingdir) 
     os.umask(umask) 
    else: 
     os._exit(0) 
else: 
    os._exit(0) 

#Close all open resources 
try: 
    os.close(0) 
    os.close(1) 
    os.close(2) 
except: 
    raise Exception("Unable to close standard output. Try running with 'nodaemon'") 
    os._exit(1) 

#Redirect output 
os.open(outfile, os.O_RDWR | os.O_CREAT) 
os.dup2(0,1) 
os.dup2(0,2) 

Następnie można użyć sygnałów, aby złapać, gdy sygnał o zabiciu został wysłany do programu i ładnie się zakończyć. Przykład z Python Docs

import signal, os 

def handler(signum, frame): 
    print 'Signal handler called with signal', signum 
    raise IOError("Couldn't open device!") 

# Set the signal handler and a 5-second alarm 
signal.signal(signal.SIGALRM, handler) 
signal.alarm(5) 

# This open() may hang indefinitely 
fd = os.open('/dev/ttyS0', os.O_RDWR) 

signal.alarm(0)   # Disable the alarm 
+0

Metoda podwójnego rozwidlenia działa jak urok! – pygabriel

0

Spróbuj question lub bardziej dokładnie przyjętego rozwiązania.

+0

Naprawdę wolałbym nie faszerować wewnętrznymi częściami programu. Heck Wolałbym raczej zachować to, czego używam, niż to zrobić. – BCS

+0

Naprawdę nie musisz zmieniać programu, jeśli jest on importowalny. Joust importuj swój main w deamon-example Run method, (replace while loop). – Ib33X

2

Istnieją moduły, które mogą być używane do demonizacji skryptu Pythona.

python-daemon implementuje dobrze zachowaną specyfikację daemona (PEP 3143).

Ostatnio na githubie pojawił się również this module, który wydaje się być bardziej pytonowy i łatwy w użyciu.