当前位置: 首页 > 知识库问答 >
问题:

Python守护进程和systemd服务

越国源
2023-03-14

我有一个简单的Python脚本作为守护程序工作。我正在尝试创建systemd脚本,以便能够在启动期间启动此脚本。

当前systemd脚本:

[Unit]
Description=Text
After=syslog.target

[Service]
Type=forking
User=node
Group=node
WorkingDirectory=/home/node/Node/
PIDFile=/var/run/zebra.pid
ExecStart=/home/node/Node/node.py

[Install]
WantedBy=multi-user.target

node.py:

if __name__ == '__main__':
    with daemon.DaemonContext():
        check = Node()
        check.run()

< code>run包含< code>while True循环。

我尝试使用< code > system CTL start zebra-node . service 运行此服务。不幸的是,服务从来没有完成状态序列-我必须按下Ctrl C。脚本正在运行,但状态是激活,过了一会儿,它改变为停用。现在我正在使用python-daemon(但是之前我没有使用它,症状也类似)。

我应该在我的脚本中实现一些附加功能还是systemd文件不正确?

共有3个答案

顾恺
2023-03-14

您没有创建PID文件。

systemd 期望您的程序以 /var/run/zebra.pid 格式编写其 PID。由于您不这样做,systemd可能认为您的程序正在失败,因此将其停用。

要添加PID文件,请安装lockfile并将代码更改为:

import daemon
import daemon.pidlockfile 

pidfile = daemon.pidlockfile.PIDLockFile("/var/run/zebra.pid")
with daemon.DaemonContext(pidfile=pidfile):
    check = Node()
    check.run()

(快速注意:< code>lockfile的一些最新更新更改了其API,使其与python-daemon不兼容。要修复此问题,请编辑< code > daemon/pidlockfile . py ,从导入中移除< code>LinkFileLock,并添加< code > from lock file . link lock file import link lock file as link file lock 。)

注意另一件事:DaemonContext将程序的工作目录更改为/,使服务文件的WorkingDirectory无用。如果您希望DaemonContext将chdir编入另一个目录,请使用DaemonContext(pidfile=pidfile,working_directory="/path/to/dir")

拓拔俊德
2023-03-14

像Schnouki和Amit描述的那样去妖魔化是可能的。但是对于systemd,这是不必要的。有两种更好的方法来初始化守护进程:套接字激活和使用sd_notify()的显式通知。

套接字激活适用于想要侦听网络端口或 UNIX 套接字或类似端口的守护程序。Systemd 将打开套接字,侦听它,然后在连接进入时生成守护程序。这是首选的 approch,因为它为管理员提供了最大的灵活性。[1]和[2]给出了一个很好的介绍,[3]描述了C API,而[4]描述了Python API。

[1]http://0pointer.de/blog/projects/socket-activation.html
[2]http://0pointer.de/blog/projects/socket-activation2.html
[3]http://www.freedesktop.org/software/systemd/man/sd_listen_fds.html
[4]http://www.freedesktop.org/software/systemd/python-systemd/daemon.html#systemd.daemon.listen_fds

显式通知意味着守护进程自己打开套接字和/或进行任何其他初始化,然后通知init它准备好了,可以为请求提供服务。这可以用“分叉协议”来实现,但实际上用sd_notify()向systemd发送通知更好。Python包装器名为systemd.daemon.notify,将是一行代码[5]。

[5]http://www . free desktop . org/software/systemd/python-systemd/daemon . html # systemd . daemon . notify

在这种情况下,单元文件的类型为notify,并调用systemd.daemon。在建立套接字后通知(“就绪=1”)。无需分叉或后台处理。

程俊力
2023-03-14

它没有完成启动顺序的原因是,对于类型分叉,您的启动过程预计将分叉并退出(请参阅$man systemd.service-搜索分叉)。

一种选择是少做。使用systemd,通常不需要创建守护进程,您可以直接运行代码而无需守护进程。

#!/usr/bin/python -u
from somewhere import Node
check = Node()
check.run()

这允许使用更简单的服务类型,称为简单,因此您的单元文件将如下所示。

[Unit]
Description=Simplified simple zebra service
After=syslog.target

[Service]
Type=simple
User=node
Group=node
WorkingDirectory=/home/node/Node/
ExecStart=/home/node/Node/node.py
StandardOutput=syslog
StandardError=syslog

[Install]
WantedBy=multi-user.target

请注意,python shebang 中的 -u 不是必需的,但是如果您将某些内容打印到 stdout 或 stderr,则 -u 确保没有输出缓冲,并且打印的行将立即被 systemd 捕获并记录在日志中。没有它,它将在一段时间内出现。

为此,我在单元文件中添加了行< code > standard output = syslog 和< code > standard error = syslog 。如果您不关心日志中的打印输出,就不要关心这些行(它们不必出现)。

虽然你的问题的标题明确地问了关于守护进程的问题,但我想,问题的核心是“如何让我的服务运行起来”,虽然使用main进程看起来简单得多(你根本不必关心守护进程),但这可以被认为是对你的问题的回答。

我认为,许多人使用守护神化只是因为“每个人都这样做”。对于 systemd,守护程序化的原因通常已经过时了。使用守护程序化可能有一些原因,但现在这种情况很少见。

编辑:将< code>python -p修正为正确的< code>python -u。感谢kmftzg

 类似资料:
  • 问题内容: 我有一个简单的Python脚本充当守护程序。我试图创建systemd脚本,以便能够在启动过程中启动此脚本。 当前的systemd脚本: node.py: 包含循环。 我尝试使用运行该服务。不幸的是,服务从未完成说明序列-我必须按Ctrl + C。脚本正在运行,但是状态为激活,一段时间后变为停用状态。现在我正在使用(但是在我尝试不使用它之前,症状是相似的)。 我应该为脚本实现一些其他功能

  • 本文向大家介绍python实现守护进程、守护线程、守护非守护并行,包括了python实现守护进程、守护线程、守护非守护并行的使用技巧和注意事项,需要的朋友参考一下 守护进程 1、守护子进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allow

  • 守护(Daemon)进程 我们可以认为守护进程就是后台服务进程,因为它会有一个很长的生命周期提供服务,关闭终端不会影响服务,也就是说可以忽略某些信号。 实现守护进程 首先要保证进程在后台运行,可以在启动程序后面加&,当然更原始的方法是进程自己fork然后结束父进程。 if (pid=fork()) { exit(0); // Parent process } 然后是与终端、进程组、会话(Ses

  • Daemonset可以确保全部(或者某些)节点上运行一个Pod的副本。 Daemonset可以确保全部(或者某些)节点上运行一个Pod的副本。当有节点加入集群时,也会为他们新增一个Pod。当有节点从集群移除时,这些Pod也会被回收。删除DaemonSet将会删除它创建的所有Pod。 Daemonset典型用法如下: 在每个节点上运行集群存守护进程 在每个节点上运行日志收集守护进程 在每个节点上运行

  • 建议使用 systemd 管理我们的服务进程。 可以参考swoole官方文档 使用方法 请确保cabal.php配置文件中的swoole.daemonize配置为关闭状态(0或false)! 'swoole' => [ // ... 'daemonize' => 0, // ... ], 在 /etc/systemd/system/目录中,创建一个 cabal.

  • 命令模式 守护进程方式启动:bin/imi server/start -d 重定向标准输入输出:bin/imi server/start -d 文件名.log 此方法只可让服务在后台运行,退出 ssh 后不被终止。 无法在服务崩溃后重新拉起,建议使用 systemd Systemd Systemd 一般都已经集成在了现代 Linux 发行版中,使用它可以实现开机自启动和守护进程等功能。 但 Sys