需求:

运行环境为CentOS 7系统,我们开发了一个程序,需要在开机时启动它,当程序进程crash之后,守护进程立即拉起进程。

解决方案:

使用CentOS 7中的init进程systemd

systemd简介

Linux Init & CentOS systemd

Linux一直以来采用init进程。例如下面的命令用来启动服务:
$ sudo /etc/init.d/apache2 start
或者\ $ service apache2 start

但是init有两个缺点:
1、启动时间长。Init进程是串行启动,只有前一个进程启动完,才会启动下一个进程。(这也是CentOS5的主要特征)
2、启动脚本复杂。Init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这使得脚本变得很长而且复杂。

Init:
Centos 5 Sys init 是启动速度最慢的,串行启动过程,无论进程相互之间有无依赖关系。
Centos6 Upstart init 相对启动速度快一点有所改进。有依赖的进程之间依次启动而其他与之没有依赖关系的则并行同步启动。
Centos7 systemd 与以上都不同。所有进程无论有无依赖关系则都是并行启动(当然很多时候进程没有真正启动而是只有一个信号或者说是标记而已,在真正利用的时候才会真正启动。)

systemd为了解决上文的问题而诞生。它的目标是,为系统的启动和管理提供一套完整的解决方案。根据linux惯例,字母d是守护进程(daemon) 的缩写。Systemd名字的含义就是 守护整个系统。Centos 7里systemd代替了init,成为了系统的第一个进程。PID为1.其他所有的进程都是它的子进程。

systemd 是 Linux 下的一款系统和服务管理器,兼容 SysV 和 LSB 的启动脚本。systemd 的特性有:支持并行化任务;同时采用 socket 式与 D-Bus 总线式激活服务;按需启动守护进程(daemon);利用 Linux 的 cgroups 监视进程;支持快照和系统恢复;维护挂载点和自动挂载点;各服务间基于依赖关系进行精密控制。

使用demo

Step1. 创建被监控脚本

$ cd ~
$ vim test_init_watch.sh

//脚本任务:间隔一秒钟输出一个date时间戳到指定到指定文件

#!/bin/bash

# test_init_watch.sh
while [ 1 ]
do
    echo `date` >> /home/cooper/log.txt
    sleep 1
done
$ chmod 777 test_init_watch.sh

//创建软链接/home/cooper/test_init_watch.sh =>/usr/sbin/sysd-test

$ sudo cd /usr/sbin
$ ln -sf /home/cooper/test_init_watch.sh sysd-test

Step2. 创建服务文件,设置init进程托管

注意:

  • systemd服务文件放置目录有系统和用户区分;系统(/usr/lib/systemd/system/)、用户(/usr/lib/systemd/user/)。
  • 在开机中没有登陆情况下就能运行的程序,应该放置在系统目录中;反之则放在用户目录中

//为了测试方便,把服务文件放在/usr/lib/systemd/system中(借鉴sshd.service):

$ cd /usr/lib/systemd/system/sysd-test.service
$ cp sshd.service sysd-test.service     
$ vim sysd-test.service

// usr/lib/systemd/system/sysd-test.service

[Unit]
Description=sysd server daemon
Documentation=no
After=no
Wants=no

[Service]
EnvironmentFile=no
ExecStart=/usr/sbin/sysd-test
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=1s

[Install]
WantedBy=multi-user.target graphic.target      #相当于runlevel:2345

// 激活开机启动。启用runlevel的2345级别

$ systemctl enable sysd-test.service

//等价于创建软链接(下面的命令不用执行)

$ cd /etc/systemd/system/multi-user.target.wants
$ ln -sf /usr/lib/systemd/system/sysd-test.service sysd-test.service
$ cd /usr/lib/systemd/system/graphical.target.wants/
$ ln -sf /usr/lib/systemd/system/sysd-test.service sysd-test.service

Step3. 启动sysd_test

//使用命令:

systemctl [start|stop|status|reload|kill] sysd-test.service

//启动

$ systemctl start sysd-test.service
$ pgrep sysd-test
$ pkill -9 sysd-test
$ pgrep sysd-test

//会发现两次pgrep进程id不一样了,表示系统自动拉起了sysd-test

//停止

$ systemctl stop sysd-test.service