大家好,欢迎来到IT知识分享网。
其实早在2007年的时候 国外的大佬已经实现了
A simple unix/linux daemon in Python – Lone Wolves – Web, game, and open source development
自己基本上没有做改动 直接搬到自己的项目中 很好用 比 nohup ./program & 好用多了!!
#!/usr/bin/env python
import sys, os, time, atexit, platform, traceback, logging,signal
class Daemon:
"""
A generic daemon class.
Usage: subclass the Daemon class and override the run() method
"""
def __init__(self, pidfile, stdin=os.devnull, stdout=os.devnull, stderr=os.devnull,home_dir='.',umask=0,verbose=1):
self.stdin = stdin #标准输入 例如键盘输入
self.stdout = stdout #标准输出 命令窗口输出
self.stderr = stderr #标准出错
self.pidfile = pidfile #pid文件绝对路径
self.home_dir = home_dir #主目录 根目录
self.umask = umask #文件权限设置掩码
self.verbose = verbose #调试开关
self.daemon_alive = True #进程是否在运行
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
"""
try:
pid = os.fork()
if pid > 0: #正常fork后 为0 否则fork没有成功
# exit first parent
sys.exit(0) #无错误 退出
except OSError as e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# decouple from parent environment
os.chdir(self.home_dir) #换到根目录
os.setsid() #获得独立进程号
os.umask(self.umask)#设置文件权限掩码
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError as e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
if sys.platform != 'darwin':
# This block breaks on OS X
# redirect standard file descriptors
sys.stdout.flush() #清除标准输入
sys.stderr.flush() #清除错误信息
si = open(self.stdin, 'r') #打开标准输入
so = open(self.stdout, 'a+') #打开标准输出
if self.stderr:#如果有自定义的出错输出
se = open(self.stderr, 'ab+', 0)
else:
se = so
os.dup2(si.fileno(), sys.stdin.fileno()) #os.dup2(fd,fd2)将一个文件描述符 fd 复制到另一个 fd2。
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
def sig_handler(signum, frame):
self.daemon_alive = False
# 注册信号处理程序
signal.signal(signal.SIGTERM, sig_handler)
signal.signal(signal.SIGINT, sig_handler)
if self.verbose >= 1:
print('daemon process started ...')
# write pidfile
atexit.register(self.delpid)
pid = str(os.getpid())
#file(self.pidfile, 'w+').write("%s\n" % pid)
with open(self.pidfile,"w+") as f:
f.write("%s\n" % pid)
def delpid(self):
os.remove(self.pidfile)
def get_pid(self):
try:
pf = open(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
except SystemExit:
pid = None
return pid
def start(self):
"""
Start the daemon
"""
# Check for a pidfile to see if the daemon already runs
if self.verbose >= 1:
print('ready to starting ......')
pid = self.get_pid()
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
if self.verbose >= 1:
print('stopping ...')
pid = self.get_pid()
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:
i = 0
while 1:
os.kill(pid, signal.SIGTERM)
time.sleep(0.1)
i = i + 1
if i % 10 == 0:
os.kill(pid,signal.SIGHUP)
except OSError as 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)
if self.verbose >= 1:
print('Stopped!')
def restart(self):
"""
Restart the daemon
"""
self.stop()
self.start()
def is_running(self):
pid = self.get_pid()
return pid and os.path.exists('/proc/%d' % pid)
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().
"""
class MyDaemon(Daemon):
def __init__(self,pidpath, func):
Daemon.__init__(self, pidpath)
self.__func = func
def run(self):
self.__func(True)
def log_uncaught_exceptions(ex_cls, ex, tb):
logging.critical(''.join(traceback.format_tb(tb)))
logging.critical('{0}: {1}'.format(ex_cls, ex))
def run(pidpath,func):
sys.excepthook = log_uncaught_exceptions
if platform.system() == "Linux":
daemon = MyDaemon(pidpath,func)
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()
elif 'console' == sys.argv[1]:
func(False)
elif 'status' == sys.argv[1]:
alive = daemon.is_running()
if alive:
print('process [%s] is running ......' % daemon.get_pid())
else:
print('daemon process stopped')
else:
print("Unknown command")
sys.exit(2)
sys.exit(0)
else:
print("usage:python %s start|stop|restart|console" % sys.argv[0])
sys.exit(2)
else:
func(False)
def daemonFunc(isdaemon):
serverStart()
reactor.run()
serverStop()
def run():
daemon.run(pidpath, daemonFunc)
if __name__ == "__main__":
run()
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/27505.html