Pythonで書いたスクリプトをデーモン化する方法
某プログラムをcronで呼び出していたのですが、これだと1分おきにしか実行できません。次のようにすれば、30秒単位で実行することもできますが、通常は1分単位で、ある時は10秒単位でというように状態によって間隔を変えて処理したかったのでデーモン化の方法を調べました。
* * * * * date & sleep 30 ; date
Chris' Python Page にてそのものずばりの例を発見しました。指定したユーザで実行できるし、init.dスクリプトを書けば、OS起動時に自動実行することもできます。すばらしー
10秒おきにログ(/var/log/pydaemon.log)に時間を書き出すサンプル
#!/usr/bin/env python
###########################################################################
# configure these paths:
LOGFILE = '/var/log/pydaemon.log'
PIDFILE = '/var/run/pydaemon.pid'
# and let USERPROG be the main function of your project
#import mymain
#USERPROG = mymain.main
###########################################################################
#based on Jurgen Hermanns http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012
import sys, os
class Log:
"""file like for writes with auto flush after each write
to ensure that everything is logged, even during an
unexpected exit."""
def __init__(self, f):
self.f = f
def write(self, s):
self.f.write(s)
self.f.flush()
def main():
#change to data directory if needed
os.chdir("/tmp")
#redirect outputs to a logfile
sys.stdout = sys.stderr = Log(open(LOGFILE, 'a+'))
#ensure the that the daemon runs a normal user
os.setegid(500) #set group first "pydaemon"
os.seteuid(500) #set user "pydaemon"
#start the user program here:
import time
while 1:
print time.ctime(time.time())
time.sleep(10)
if __name__ == "__main__":
# do the UNIX double-fork magic, see Stevens' "Advanced
# Programming in the UNIX Environment" for details (ISBN 0201563177)
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError, e:
print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# decouple from parent environment
os.chdir("/") #don't prevent unmounting....
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent, print eventual PID before
#print "Daemon PID %d" % pid
open(PIDFILE,'w').write("%d"%pid)
sys.exit(0)
except OSError, e:
print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# start the daemon main loop
main()
通常は、実際に実行するプログラムを別に用意しておいて、呼び出すのでしょうね(import mymainの箇所を参照)。










