python daemon化你的程序
在之前的树莓派网关项目中遇到了这样一个问题,由于要把网关写的Server持续运行,尤其是要加电自动开启。发现ssh登录开启服务程序之后,当把pty退出时Server端自动断开了,这里想到的APUE中第九章的内容,回顾了下关于会话首进程,进程组,控制终端的概念,所以我们需要把自己写的Server端变为父进程为init(1)的守护进程。
--->首先想到的办法是使用nohup命令,这里遇到一个坑:
当我们用nohup去处理shell脚本时是没有问题的,但是在尝试执行一个Python脚本时:
nohup python tcp_server.py > ser_log.out 2>&1 &
结果很出了问题:竟然查不到重定向的ser_log.out的输出!后来发现:python的输出有缓冲,导致ser_log.out并不能够马上看到输出。
我们应该加 -u参数,使得python不启用缓冲,如下:
nohup python -u tcp_server.py > ser_log.out 2>&1 &
#!/usr/bin/env python # coding:utf-8 import os,sys,time def daemon_init(stdin='/dev/null',stdout='/dev/null',stderr='/dev/null'): sys.stdin = open(stdin,'r') sys.stdout = open(stdout,'a+') sys.stderr = open(stderr,'a+') try: pid = os.fork() if pid > 0: #parrent os._exit(0) except OSError,e: sys.stderr.write("first fork failed!!"+e.strerror) os._exit(1) # 子进程, 由于父进程已经退出,所以子进程变为孤儿进程,由init收养 '''setsid使子进程成为新的会话首进程,和进程组的组长,与原来的进程组、控制终端和登录会话脱离。''' os.setsid() '''防止在类似于临时挂载的文件系统下运行,例如/mnt文件夹下,这样守护进程一旦运行,临时挂载的文件系统就无法卸载了,这里我们推荐把当前工作目录切换到根目录下''' os.chdir("/") '''设置用户创建文件的默认权限,设置的是权限“补码”,这里将文件权限掩码设为0,使得用户创建的文件具有最大的权限。否则,默认权限是从父进程继承得来的''' os.umask(0) try: pid = os.fork() #第二次进行fork,为了防止会话首进程意外获得控制终端 if pid > 0: os._exit(0) #父进程退出 except OSError,e: sys.stderr.write("second fork failed!!"+e.strerror) os._exit(1) # 孙进程 # for i in range(3,64): # 关闭所有可能打开的不需要的文件,UNP中这样处理,但是发现在python中实现不需要。 # os.close(i) sys.stdout.write("Daemon has been created! with pid: %d\n" % os.getpid()) sys.stdout.flush() #由于这里我们使用的是标准IO,回顾APUE第五章,这里应该是行缓冲或全缓冲,因此要调用flush,从内存中刷入日志文件。 def main(): print '========main function start!============' #在调用daemon_init函数前是可以使用print到标准输出的,调用之后就要用把提示信息通过stdout发送到日志系统中了 daemon_init('/dev/null','/tmp/daemon.log','/tmp/daemon.err') # 调用之后,你的程序已经成为了一个守护进程,可以执行自己的程序入口了 time.sleep(10) #daemon化自己的程序之后,sleep 10秒,模拟阻塞 if __name__ == '__main__': main()
这样,通过调用daemon_init方法,就可以把自己的程序变为守护进程了,实现了nohup的功能。这样做就更加灵活了,之后的事情就要具体问题具体分析了,比如针对自己实际的应用程序来决定是否要设置umask,是否要关闭不必要的文件描述符,是否要改变当前工作目录等等。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?