在systemd下如何编写我们的守护进程,利用systemd管理我们的守护进程

原创 2015年11月18日 17:36:28

       前言:在sysv init与upstart方式下,我们编写守护进程的方法可参见我写的其它文章,但思想与方法来源都是那本圣经《unix环境高级编程》,基本思路就是两次fork,调用setsid()脱离终端(如果有的话),标准输出入、标准输出、标准出错重定向等等;

     最近的一些linux distribution开始采用systemd作为sysv init和upstart的替代,如果我们想让自己的程序(服务)被systemd管理,则编写守护进程则要遵循一些systemd下的规则了....


一:systemd简单介绍

        http://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/index.html

二:systemd下编写守护进程遵循的几点规则

        开发人员需要了解 systemd 的更多细节。比如您打算开发一个新的系统服务,就必须了解如何让这个服务能够被 systemd 管理。这需要您注意以下这些要点:

  • 后台服务进程代码不需要执行两次派生来实现后台精灵进程,只需要实现服务本身的主循环即可。(传统编写守护进程要至少调用一次fork,然后停止父进程)
  • 不要调用 setsid(),交给 systemd 处理
  • 不再需要维护 pid 文件。(传统编写守护进程,会自己在某个目录下,生成pid文件,一是记录本守护进程pid,另外一点是防止本守护进程被多次重启而导致出错或者导致多个实例在运行)
  • Systemd 提供了日志功能,服务进程只需要输出到 stderr 即可,无需使用 syslog。(传统编写守护进程我们要将标准输出、出错、输入关闭或者重定向,日志信息都是发往rsyslog)
  • 处理信号 SIGTERM,这个信号的唯一正确作用就是停止当前服务,不要做其他的事情。(传统守护进程一般SIGTERM也是用来做这种事情的)
  • SIGHUP 信号的作用是重启服务。(传统数据进程一般SIGHUP也是做这种事情的)
  • 需要套接字的服务,不要自己创建套接字,让 systemd 传入套接字。(这个承接systemd快速启动优点而设立的,可以实现这个特点,也可以不实现)
  • 使用 sd_notify()函数通知 systemd 服务自己的状态改变。一般地,当服务初始化结束,进入服务就绪状态时,可以调用它。(没用过)

三:实例编写

      1.python代码:

#! /usr/bin/python
import sys, os, socket, signal
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
addr = '', 9090
serv.bind(addr)
serv.listen(5)

def sighup(num1, num2):
    sys.stderr.write("We receive SIGHUP signal...\nwe will reload the configuration file...\n")
def sigterm(num1, num2):
    sys.stderr.write("We kill us greacefully...\n")
    os._exit(0)

#handle signal SIGHUB
signal.signal(signal.SIGHUP, sighup)

#handler signal SIGTERM
signal.signal(signal.SIGTERM, sigterm)

sys.stderr.write("My self daemon start...\n")
while True:
    try:
        conn, addr = serv.accept()
    except Exception:
        continue
    try:
        pid = os.fork()
        if pid == 0:
           #child process close serv_socket_object of parent
           serv.close()
           time.sleep(5)
           os._exit(0)
        else:
           #parent process close conn_socket_object of child
           conn.close()
    except OSError:
        #if we use conn.close(), we must wait for python gc to 
        #really close the socket connection
        conn.shutdown(socket.SHUT_RDWR)

这就是一个普通的python程序,我们编写了信号处理函数,分别针对SIGHUB(用于重新读取配置文件)、SIGTERM(用于杀死自己)

    2.编写service文件

[root@localhost system]# pwd
/etc/systemd/system
[root@localhost system]# cat mydaemon.service 
[Unit]
Description=myDaemon 
[Service]
ExecStart=/root/mydaemon.py
ExecStop=/bin/kill -TERM $MAINPID
ExecReload=/bin/kill -HUP $MAINPID
killMode=process
After=network.target
[Install]
WantedBy=multi-user.target


我们在/etc/systemd/system新建mydaemon.service文件,文件内容如上

  3. 命令执行

接着我们执行:

[root@localhost system]# systemctl daemon-reload


再执行:

[root@localhost system]# systemctl start mydaemon

查看一下状态:

[root@localhost system]# systemctl status mydaemon
mydaemon.service - myDaemon
   Loaded: <span style="color:#ff0000;">loaded</span> (/etc/systemd/system/mydaemon.service; <span style="color:#ff0000;">disabled</span>)
   Active: <span style="color:#ff0000;">active</span> (running) since 三 2015-11-18 16:35:15 CST; 45min ago
 Main PID: 6873 (mydaemon.py)
   CGroup: /system.slice/mydaemon.service
           └─<span style="color:#ff0000;">6873 /usr/bin/python /root/mydaemon.py</span>

11月 18 16:35:15 localhost.localdomain systemd[1]: Started myDaemon.
11月 18 16:35:15 localhost.localdomain mydaemon.py[6873]: My self daemon start...
11月 18 16:35:36 localhost.localdomain systemd[1]: Reloading myDaemon.
11月 18 16:35:36 localhost.localdomain mydaemon.py[6873]: We receive SIGHUP signal...and we will reload the...ile
11月 18 16:35:36 localhost.localdomain systemd[1]: Reloaded myDaemon.
11月 18 17:19:00 localhost.localdomain systemd[1]: [/etc/systemd/system/mydaemon.service:7] Unknown lvalue...ice'
11月 18 17:19:00 localhost.localdomain systemd[1]: [/etc/systemd/system/mydaemon.service:8] Unknown lvalue...ice'
11月 18 17:20:12 localhost.localdomain systemd[1]: Started myDaemon.
Hint: Some lines were ellipsized, use -l to show in full.
正常启动了,不过貌似我配置文件写的有点问题


现在我们验证下systemd提供的日志功能:

[root@localhost system]# systemctl reload mydaemon
日志内容(命令内容:journalctl --unit mydaemon):

11月 18 17:20:12 localhost.localdomain systemd[1]: Started myDaemon.
11月 18 17:23:56 localhost.localdomain systemd[1]: Reloading myDaemon.
11月 18 17:23:56 localhost.localdomain mydaemon.py[6873]: <span style="color:#ff0000;">We receive SIGHUP signal...and we will reload the config</span>
11月 18 17:23:56 localhost.localdomain systemd[1]: Reloaded myDaemon.
红色内容就是我们在程序中sys.stderr.write()的内容


当然,我们也可以设置为开机启动,命令

[root@localhost system]# systemctl enable mydaemon









编写systemd service文件

转自:openSUSE:How to write a systemd service 本教程简单的描述了如何从零开始编写一个 Systemd 服务文件、SysV init 脚本到 Syste...
  • djskl
  • djskl
  • 2015年06月28日 14:52
  • 10563

编写systemd下服务脚本

编写systemd下服务脚本 Red Hat Enterprise Linux 7(RHEL 7)已经将服务管理工具从SysVinit和Upstart迁移到了systemd上,相应的服务脚本也需要改...
  • u010127879
  • u010127879
  • 2014年07月21日 16:16
  • 12634

CentOS 7之Systemd详解之服务单元设置system.service

名称 systemd.service - 服务单元配置 概要 service.service 描述 以 .service 结尾的单元文件,用于封装一个被 systemd 监...
  • yuesichiu
  • yuesichiu
  • 2016年05月23日 21:59
  • 8384

Systemd及service文件解析

Systemd及service文件解析   Systemd是Linux下的一款系统和服务管理器,兼容SysV和LSB的启动脚本。Systemd的特征有:支持并行化任务;同时采用socket式与D-Bu...
  • u010255859
  • u010255859
  • 2017年07月05日 16:00
  • 223

systemd实现python的守护进程

守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。(摘自百度百科)之前有转过一遍python实现守护进程方法的博客,这次我们看看用s...
  • luckytanggu
  • luckytanggu
  • 2016年12月05日 17:48
  • 2040

systemd系统守护进程

systemd提供更优秀的框架以表示系统服务间的依赖关系 实现系统初始化时服务的并行启动,同时达到降低Shell的系统开销的效果 systemd的目标是:尽可能启动更少进程;尽可能将更多进程并行启...
  • permike
  • permike
  • 2016年11月24日 13:04
  • 668

Systemd启动守护进程/代替Cron/日志管理

Systemd 是 Linux 系统工具,用来启动守护进程,已成为大多数发行版的标准配置。 本文介绍它的基本用法,分为上下两篇。今天介绍它的主要命令,下一篇介绍如何用于实战。一、由来历史上,Linu...
  • lilongsy
  • lilongsy
  • 2017年12月07日 17:42
  • 211

linux下如何使用systemctl管理systemd服务与单元

先来个简单总结(后面才是from的链接的内容): 启动一个服务:systemctl start postfix.service 关闭一个服务:systemctl stop postfix.serv...
  • drdairen
  • drdairen
  • 2016年05月18日 09:00
  • 4347

走进Linux之systemd启动过程

编译自:http://linoxide.com/linux-how-to/systemd-boot-process/作者: Aun Raza 原创:LCTT https://linux.cn/a...
  • YuZhiHui_No1
  • YuZhiHui_No1
  • 2016年08月17日 10:44
  • 829

system()函数源码

system()函数功能强大,很多人用却对它的原理知之甚少先看linux版system函数的源码: #include #include #include #include ...
  • ghevinn
  • ghevinn
  • 2012年08月28日 14:45
  • 2572
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在systemd下如何编写我们的守护进程,利用systemd管理我们的守护进程
举报原因:
原因补充:

(最多只允许输入30个字)