在Google上搜索会显示x2代码段.第一个结果是这个代码配方有很多文档和解释,以及下面的一些有用的讨论.
但是,另一个代码示例虽然不包含如此多的文档,但包含用于传递命令(如启动,停止和重新启动)的示例代码.它还会创建一个PID文件,可以方便地检查守护程序是否已在运行等.
这些示例都解释了如何创建守护进程.还有其他事情需要考虑吗?一个样本比另一个好,为什么?
big*_*ose 162
在成为一个表现良好的守护进程时,有许多需要注意的事情:
防止核心转储(许多守护程序以root身份运行,核心转储可能包含敏感信息)
在chroot
监狱里表现正确
为用例适当地设置UID,GID,工作目录,umask和其他进程参数
放弃提升suid
,sgid
特权
关闭所有打开的文件描述符,具有取决于用例的排除
正确的行为,如果启动一个已经脱离上下文中,如init
,inetd
等
为敏感的守护程序行为设置信号处理程序,但也使用由用例确定的特定处理程序
重定向标准流stdin
,stdout
,stderr
因为守护进程不再具有控制终端
在进程终止时允许适当的清理
实际上成为一个守护进程而不会导致僵尸
其中一些是标准的,如规范的Unix文献(UNIX环境中的高级编程,已故的W. Richard Stevens,Addison-Wesley,1992)中所述.其他的,例如流重定向和PID文件处理,是大多数守护程序用户期望的常规行为,但是标准化程度较低.
所有这些都包含在PEP 3143 "标准守护进程库"规范中.该蟒蛇守护参考实现工作在Python 2.7版或更高版本,和Python 3.2或更高版本.
Jef*_*uer 161
当前解决方案
PEP 3143(标准守护程序进程库)的参考实现现在可用作python-daemon.
历史答案
Sander Marechal的代码示例优于原始版本,最初发布于2004年.我曾经为Pyro贡献了一个守护程序,但如果我不得不这样做,可能会使用Sander的代码.
Dus*_*and 94
这是我开始使用的基本"Howdy World"Python守护进程,当我开发一个新的守护进程应用程序时.
#!/usr/bin/python
import time
from daemon import runner
class App():
def __init__(self):
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
self.pidfile_path = '/tmp/foo.pid'
self.pidfile_timeout = 5
def run(self):
while True:
print("Howdy! Gig'em! Whoop!")
time.sleep(10)
app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()
Run Code Online (Sandbox Code Playgroud)
请注意,您需要该python-daemon
库.您可以通过以下方式安装:
pip install python-daemon
Run Code Online (Sandbox Code Playgroud)
然后启动它./howdy.py start
,然后停止它./howdy.py stop
.
Vil*_*iam 42
注意python-daemon包解决了守护进程背后的许多问题.
它可以实现的其他功能(来自Debian软件包描述):
Luk*_*pin 12
可能不是问题的直接答案,但systemd可用于将您的应用程序作为守护程序运行.这是一个例子:
[Unit]
Description=Python daemon
After=syslog.target
After=network.target
[Service]
Type=simple
User=<run as user>
Group=<run as group group>
ExecStart=/usr/bin/python <python script home>/script.py
# Give the script some time to startup
TimeoutSec=300
[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)
我更喜欢这种方法,因为很多工作都是为您完成的,然后您的守护程序脚本的行为与系统的其他部分类似.
-Orby
此函数将应用程序转换为守护程序:
import sys
import os
def daemonize():
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError as err:
sys.stderr.write('_Fork #1 failed: {0}\n'.format(err))
sys.exit(1)
# decouple from parent environment
os.chdir('/')
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError as err:
sys.stderr.write('_Fork #2 failed: {0}\n'.format(err))
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = open(os.devnull, 'r')
so = open(os.devnull, 'w')
se = open(os.devnull, 'w')
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
Run Code Online (Sandbox Code Playgroud)
小智 6
因为python-daemon还没有支持python 3.x,并且从邮件列表中可以读取的内容,它可能永远不会,我已经编写了PEP 3143的新实现:pep3143daemon
pep3143daemon应该至少支持python 2.6,2.7和3.x.
它还包含一个PidFile类.
该库仅依赖于标准库和六个模块.
它可以用作python-daemon的替代品.
这是文档.
恐怕@Dustin 提到的守护程序模块对我不起作用。相反,我安装了python-daemon并使用了以下代码:
# filename myDaemon.py
import sys
import daemon
sys.path.append('/home/ubuntu/samplemodule') # till __init__.py
from samplemodule import moduleclass
with daemon.DaemonContext():
moduleclass.do_running() # I have do_running() function and whatever I was doing in __main__() in module.py I copied in it.
Run Code Online (Sandbox Code Playgroud)
跑步很容易
> python myDaemon.py
Run Code Online (Sandbox Code Playgroud)
只是为了完整起见,这里是 samplemodule 目录内容
>ls samplemodule
__init__.py __init__.pyc moduleclass.py
Run Code Online (Sandbox Code Playgroud)
moduleclass.py 的内容可以是
class moduleclass():
...
def do_running():
m = moduleclass()
# do whatever daemon is required to do.
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
270844 次 |
最近记录: |