自定义一个守护进程的服务

by kingzcheung on May 19, 2018

无论是nginx,apache,还是php-fpm,ftp,甚至ssh,都是以service的形式存在于系统之中,有时候我们可能需要为自己写的脚本做成一个守护进程的服务。Systemd 是用来启动守护进程的工具,平时我们使用的systemctl就是用 Systemd 的管理命令。

sudo systemctl start nginx.service #立即启动一个服务
sudo systemctl restart nginx.service #重启一个服务
sudo systemctl stop nginx.service #停止一个服务
sudo systemctl reload nginx.service #重载服务配置
sudo systemctl status nginx.service #查看服务状态
sudo systemctl daemon-reload # 重载Systemd 配置
.....
#日志相关
sudo journalctl #查看所有日志
sudo journalctl  --since="2012-10-30 18:17:16" #根据时间查看日志
sudo journalctl -u nginx.service -n #根据服务查看日志, -n表示行数,默认10行
sudo journalctl -f # 实时显示日志,和tail -f 有点像
......

以一个php脚本为例子,实现一个每2秒输出文本到控制台:

环境:

  • ubuntu 16.04
  • PHP 7.2.4

PHP 脚本如下:

#! /usr/bin/env php
<?php
    
$i = 0;
while (true){
    print_r($i.PHP_EOL);
    sleep(2);
    $i++;
}

/lib/systemd/system下创建一个文件 test.service ,内容如下:

[Unit]
Description=test service

[Service]
Type=simple
User=root
Group=root
ExecStart=/root/test.php
WorkingDirectory=/root
Restart=always

[Install]
WantedBy=multi-user.target

每一个service都是一个unit,每个unit有一个配置文件,这些文件要么存在于 /usr/lib/systemd/system里,要么/lib/systemd/system里,使用下面的命令会往 /etc/systemd/system添加软连接:

sudo systemctl enable nginx.service

配置文件的格式分为几大块:

[Unit]用来定义Unti的一些基本信息,主要字段有:

  • Description :描述服务
  • Documentation: 关于服务的文档
  • Requires :必须依赖的其他Unit
  • Wants: 可选依赖的其他Unit
  • Before:当前服务要在此选项的Unit之前启动
  • After:当前服务要在此选项的Unti之后启动

[Service]用来定义 service 类型的unit的配置,主要字段有:

  • Type=simple 定义类型,可选还有:forking,oneshot,dbus,notify
  • ExecStart:启动当前服务的命令
  • ExecStartPre:启动当前服务之前执行的命令
  • ExecStartPost:启动当前服务之后执行的命令
  • ExecReload:重启当前服务时执行的命令
  • ExecStop:停止当前服务时执行的命令
  • ExecStopPost:停止当其服务之后执行的命令
  • RestartSec:自动重启当前服务间隔的秒数
  • Environment:指定环境变量

[Install]定义如何启动

  • WantedBy:表示 Unit 运行 sudo systemctl enable xxx.service时 符号链接会放入/etc/systemd/system目录下面以 Target 名 + .wants后缀构成的子目录中
  • RequiredBy: Unit 运行sudo systemctl enable xxx.service时,符号链接会放入/etc/systemd/system目录下面以 Target 名 + .required后缀构成的子目录中
  • Alias:当前 Unit 可用于启动的别名
  • Also:当前 Unit 运行sudo systemctl enable xxx.service时,会被同时enbale的其他 Unit

查看进程 ps -ef |grep test,结果如下:

root     23018     1  0 22:31 ?        00:00:00 php /root/test.php
root     23110 21736  0 22:34 pts/2    00:00:00 grep --color=auto test

发现进程已经启动,进程号为23018.

查看日志:

sudo journalctl -u nginx.service

脚本日志如下:

May 19 22:31:34 iZj6cfvxo1vhihy2q9x2coZ systemd[1]: Stopping test service...
May 19 22:31:34 iZj6cfvxo1vhihy2q9x2coZ systemd[1]: Stopped test service.
May 19 22:31:34 iZj6cfvxo1vhihy2q9x2coZ systemd[1]: Started test service.
May 19 22:31:34 iZj6cfvxo1vhihy2q9x2coZ test.php[23018]: 0
May 19 22:31:36 iZj6cfvxo1vhihy2q9x2coZ test.php[23018]: 1
May 19 22:31:38 iZj6cfvxo1vhihy2q9x2coZ test.php[23018]: 2

发现已经每2秒输出一个数字。