废话不多说,两个py脚本,main.py 为主脚本
main.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys, getopt, time, os
import signal
import multiprocessing
from daemon import Daemon
class JobServer(multiprocessing.Process):
def stopsignal(self, signum, frame):
self.substoptag = 1
def __init__(self):
multiprocessing.Process.__init__(self)
self.substoptag = 0
def run(self):
signal.signal(signal.SIGTERM,self.stopsignal)
print "sub process run"
while True:
time.sleep(5)
## 这里做点事情 ##
if self.substoptag == 1:
print "exit sub process"
break;
class Main(Daemon):
# 接收信号
def stopsignal(self, signum, frame):
self.stoptag = 1
def __init__(self, runpath, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.runpath = runpath
self.pidfile = pidfile
self.stoptag = 0
# 进程列表
self.procs = []
def run(self):
print "Job start"
proc = [ JobServer(),"one job" ]
self.procs.append(proc)
# 启动一个进程
proc[0].start()
signal.signal(signal.SIGTERM,self.stopsignal)
while True:
time.sleep(5)
if self.stoptag == 1:
print "Job stop"
for pro in self.procs:
print "stop sub process %s" % pro[1]
pro[0].terminate()
break
if __name__ == "__main__":
# 获取运行路径
runpath = os.path.split( os.path.realpath( sys.argv[0] ) )[0]
# 初始化主类,并传入pid文件名
daemon = Main(runpath, runpath + '/daemon.pid')
if len(sys.argv) >= 2:
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
daemon.stop()
elif 'restart' == sys.argv[1]:
daemon.restart()
else:
print("Unknown command")
sys.exit(2)
sys.exit(0)
else:
print("usage: %s start|stop|restart" % sys.argv[0])
sys.exit(2)
daemon.py
#!/usr/bin/env python
import sys, os, time, atexit
from signal import SIGTERM
class Daemon:
"""
A generic daemon class.
Usage: subclass the Daemon class and override the run() method
"""
def __init__(self, runpath, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
self.runpath = runpath
def daemonize(self):
"""
do the UNIX double-fork magic, see Stevens' "Advanced
Programming in the UNIX Environment" for details (ISBN 0201563177)
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
"""
# decouple from parent environment
#os.chdir("/")
#os.setsid()
#os.umask(0)
# do second fork
sys.stdout.flush()
sys.stderr.flush()
# write pidfile
atexit.register(self.delpid)
pid = str(os.getpid())
file(self.pidfile,'w+').write("%s\n" % pid)
def delpid(self):
os.remove(self.pidfile)
def start(self):
"""
Start the daemon
"""
# Check for a pidfile to see if the daemon already runs
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if pid:
message = "pidfile %s already exist. Daemon already running?\n"
sys.stderr.write(message % self.pidfile)
sys.exit(1)
# Start the daemon
self.daemonize()
self.run()
def stop(self):
"""
Stop the daemon
"""
# Get the pid from the pidfile
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if not pid:
message = "pidfile %s does not exist. Daemon not running?\n"
sys.stderr.write(message % self.pidfile)
return # not an error in a restart
# Try killing the daemon process
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError, err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)
def restart(self):
"""
Restart the daemon
"""
self.stop()
self.start()
def run(self):
"""
You should override this method when you subclass Daemon. It will be called after the process has been
daemonized by start() or restart().
"""
使用方法
后台启动 nohup ./main.py start &
关闭 ./main.py stop
重启 ./main.py restart