类型
oneshot
这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置 RemainAfterExit=yes 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态。
notify
与 Type=simple 相同,但约定服务会在就绪后向 systemd 发送一个信号。这一通知的实现由 libsystemd-daemon.so 提供。
dbus
若以此方式启动,当指定的 BusName 出现在DBus系统总线上时,systemd认为服务就绪。
idle
systemd会等待所有任务处理完成后,才开始执行 idle 类型的单元。其他行为与 Type=simple 类似。
forking
systemd认为当该服务进程fork,且父进程退出后服务启动成功。对于常规的守护进程(daemon),除非你确定此启动方式无法满足需求,使用此类型启动即可。使用此启动类型应同时指定 PIDFile=,以便 systemd 能够跟踪服务的主进程
simple
(默认值) systemd认为该服务将立即启动。服务进程不会 fork 。如果该服务要启动其他服务,不要使用此类型启动,除非该服务是socket 激活型。
配置
文件格式
[Unit]
Description=test service
[Service]
Type=simple
ExecStart=/tmp/test.sh start
ExecStop=/tmp/test.sh stop
ExecReload=/tmp/test.sh reload
[Install]
WantedBy=multi-user.target
示例
我们举一个simple的例子,一个forking的例子。
simple示例
服务程序
建立模拟服务程序 /tmp/test.sh 内容如下:
#!/bin/sh
cmd="$1"
echo "`date`> [$cmd]" >> /tmp/test.log
if [ "start" = "$cmd" ] ; then
while [ 1 ] ; do
sleep 1
echo "`date`> wait..." >> /tmp/test.log
done
fi
配置文件
建立服务配置文件 /lib/systemd/system/test.service 内容如下:
[Unit]
Description=test service
[Service]
Type=simple
ExecStart=/tmp/test.sh start
ExecStop=/tmp/test.sh stop
ExecReload=/tmp/test.sh reload
[Install]
WantedBy=multi-user.target
启动服务
执行如下命令
systemctl start test.service
查看日志文件,可以看到如下内容
Wed Jul 11 14:04:23 UTC 2018> [start]
Wed Jul 11 14:04:24 UTC 2018> wait...
Wed Jul 11 14:04:25 UTC 2018> wait...
Wed Jul 11 14:04:26 UTC 2018> wait...
停止服务
执行如下命令
systemctl stop test.service
查看日志文件,可以看到如下内容
Wed Jul 11 14:04:23 UTC 2018> [start]
Wed Jul 11 14:04:24 UTC 2018> wait...
Wed Jul 11 14:04:25 UTC 2018> wait...
Wed Jul 11 14:04:26 UTC 2018> wait...
Wed Jul 11 14:04:27 UTC 2018> wait...
Wed Jul 11 14:04:40 UTC 2018> [stop]
重启服务
执行如下命令
systemctl restart test.service
查看日志文件,可以看到如下内容
Wed Jul 11 14:14:06 UTC 2018> wait...
Wed Jul 11 14:14:06 UTC 2018> [stop]
Wed Jul 11 14:14:06 UTC 2018> [start]
Wed Jul 11 14:14:07 UTC 2018> wait...
刷新服务
执行如下命令
systemctl reload test.service
查看日志文件,可以看到如下内容
Wed Jul 11 14:14:32 UTC 2018> wait...
Wed Jul 11 14:14:32 UTC 2018> [reload]
Wed Jul 11 14:14:33 UTC 2018> wait...
forking示例
服务程序
建立模拟服务程序 /tmp/test.sh 内容如下:
#!/bin/sh
cmd="$1"
### start major process
if [ "daemon" = "$cmd" ] ; then
echo "`date`> [$cmd]" >> /tmp/test.log
/tmp/test.sh &
exit
fi
### stop major process
if [ "quit" = "$cmd" ] ; then
echo "`date`> [$cmd]" >> /tmp/test.log
pid="`cat /tmp/test.pid`"
if [ "" = "`ps -ax|awk '{print $1}'|grep -e "^${pid}$"`" ] ; then
/bin/rm -f /tmp/test.pid
else
/bin/kill $pid
fi
exit
fi
### reload
if [ ! "" = "$cmd" ] ; then
echo "`date`> [$cmd]" >> /tmp/test.log
exit
fi
### do major process
pid="/tmp/test.pid"
if [ -f "$pid" ] ; then
echo "it's already running with PID `cat /tmp/test.pid`"
exit
fi
echo "$$" > /tmp/test.pid
while [ 1 ] ; do
sleep 1
echo "`date`> wait..." >> /tmp/test.log
done
配置文件
建立服务配置文件 /lib/systemd/system/test.service 内容如下:
[Unit]
Description=test service
[Service]
Type=forking
PIDFile=/tmp/test.pid
ExecStart=/tmp/test.sh daemon
ExecStop=/tmp/test.sh quit
ExecReload=/tmp/test.sh reload
[Install]
WantedBy=multi-user.target
启动服务
执行如下命令
systemctl start test.service
查看日志文件,可以看到如下内容
Wed Jul 11 14:50:29 UTC 2018> [daemon]
Wed Jul 11 14:50:30 UTC 2018> wait...
Wed Jul 11 14:50:31 UTC 2018> wait...
Wed Jul 11 14:50:32 UTC 2018> wait...
停止服务
执行如下命令
systemctl stop test.service
查看日志文件,可以看到如下内容
Wed Jul 11 14:50:29 UTC 2018> [daemon]
Wed Jul 11 14:50:30 UTC 2018> wait...
Wed Jul 11 14:50:31 UTC 2018> wait...
Wed Jul 11 14:50:32 UTC 2018> wait...
Wed Jul 11 14:50:33 UTC 2018> wait...
Wed Jul 11 14:50:37 UTC 2018> [quit]
重启服务
执行如下命令
systemctl restart test.service
查看日志文件,可以看到如下内容
Wed Jul 11 14:50:54 UTC 2018> wait...
Wed Jul 11 14:50:54 UTC 2018> [quit]
Wed Jul 11 14:50:54 UTC 2018> [daemon]
Wed Jul 11 14:50:55 UTC 2018> wait...
刷新服务
执行如下命令
systemctl reload test.service
查看日志文件,可以看到如下内容
Wed Jul 11 14:51:00 UTC 2018> wait...
Wed Jul 11 14:51:01 UTC 2018> [reload]
Wed Jul 11 14:51:01 UTC 2018> wait...
总结
普通服务程序
普通服务程序使用simple类型启动,启动后系统会记录其PID,停止时系统会自动杀死进程。
适用于自己手写的一些脚本程序,这些脚本(long run)会一直执行不会中断。比起放到crontabs里的好处是,我们可以通过stop命令随时停止它。
守护进程服务程序
守护进程服务程序使用forking类型启动,因为启动daemon的逻辑是我们自己实现的,所以我们要告诉系统PID文件放哪里了以证明系统是“活着”的。
停止服务的处理也需要我们自己实现,我们需要自己读取PID文件,并查找进程,回收资源,记录日志,杀死进程等等操作。
适用于server类的程序,比如:httpd、mysqld等等。