Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 启动我的deamon时Systemctl阻塞_Python_Linux_Daemon_Systemd - Fatal编程技术网

Python 启动我的deamon时Systemctl阻塞

Python 启动我的deamon时Systemctl阻塞,python,linux,daemon,systemd,Python,Linux,Daemon,Systemd,我已经用Python编写了一个小守护程序,其中包括: #!/usr/bin/python3 import time import click import daemonocle from daemonocle.cli import DaemonCLI @click.command(cls=DaemonCLI, daemon_params={'pidfile': '/var/run/daemon.pid'}) def main(): while True: time.

我已经用Python编写了一个小守护程序,其中包括:

#!/usr/bin/python3

import time
import click
import daemonocle

from daemonocle.cli import DaemonCLI

@click.command(cls=DaemonCLI, daemon_params={'pidfile': '/var/run/daemon.pid'})
def main():
    while True:
        time.sleep(3)

if __name__ == '__main__':
    main()
它工作得很好。如果我执行以下操作,我将获得良好的退出状态
0

$ sudo ./daemon start 
Starting daemon ... OK    

$ echo $?
0
然后我写了一个
systemd
服务文件:

[Unit]
SourcePath=/home/pi/daemon/daemon
Description=My First Daemon
Before=multi-user.target
After=mosquitto.target

[Service]
Type=forking
PIDFile=/var/run/daemon.pid
Restart=no
ExecStart=/home/pi/daemon/daemon start
ExecStop=/home/pi/daemon/daemon stop
ExecReload=/home/pi/daemon/daemon reload
如果我尝试使用
systemctl
运行我的守护程序,命令将保持阻塞状态:

$ sudo systemctl start daemon
^C
$ sudo systemctl status daemon
? daemon.service - XEMWAY Demo Service
   Loaded: loaded (/home/pi/daemon/daemon; static; vendor preset: enabled)
   Active: activating (start) since Wed 2019-02-13 13:47:40 GMT; 12s ago
  Process: 13044 ExecStop=/home/pi/daemon/daemon stop (code=exited, status=0/SUCCESS)
 Main PID: 12304 (code=exited, status=143); Control PID: 13079 (daemon)
   CGroup: /system.slice/daemon.service
           +-13079 /usr/bin/python3 /home/pi/daemon/daemon start
           +-13081 /usr/bin/python3 /home/pi/daemon/daemon start
一分钟后,系统显示:

2月13日13:49:10 raspberrypi systemd[1]:daemon.service:装置进入故障状态。 2月13日13:49:10 raspberrypi systemd[1]:daemon.service:失败,结果为“超时”


这有什么问题?

问题是您的服务自己创建守护进程,而systemd不知道。它只是一个简单的程序,在systemd运行很短时间后就可以退出。要使用
简单
而不是
分叉

Type=simple
Systemd仍将作为守护进程跟踪您的进程,因为它知道其pid:

systemctl状态测试2.服务

* test2.service - My First Daemon
   Loaded: loaded (/tmp/a.py; static; vendor preset: disabled)
   Active: active (running) since Wed 2019-02-13 16:06:27 EET; 5s ago
 Main PID: 18104 (python)
    Tasks: 2 (limit: 4915)
   Memory: 10.1M
   CGroup: /system.slice/test2.service
           |-18104 /usr/bin/python /tmp/a.py start
           `-18115 /usr/bin/python /tmp/a.py start

也许使用
one-shot
比使用
forking
更容易,而且不使用fork?不,这不是因为我的脚本已经是一个守护程序系统,而其他服务监视工具更喜欢不使用fork的守护程序。如果更改守护进程或向其添加标志,使其不会脱离第一个进程,则可以使其类型=简单,并且不需要PID文件或任何东西。我不了解的是,我的Python守护进程会分叉,因为当我执行
/daemon start
时,它会启动并返回,但守护进程仍保留在内存中。那么
分叉
守护进程的含义是什么呢?据我所知,它并不分叉。只创建一个子进程并将其与主进程分离。如果我错了,请纠正我,我没有太多时间阅读文档:(你可能比我更了解这一点。我说不出子进程和fork之间的区别:(我可以比
os阅读。fork
创建子进程:(现在我很困惑,是的,但是fork不是唯一一个创建子进程的方法。
exec
也创建子进程。