CentOS7添加一个systemd服务教程
一、说明
1.1 背景说明
刚工作时D运营商多用CentOS6,在很长的一段时间内搞不清这两个问题:为什么yum安装的mysql服务用service命令就能启动了、如果自己rpm安装的或自己写的程序也想改成能用service命令启动那又该怎么做。
后来更多用了CentOS7,CentOS7又改用systemctl,和service又有所不同。
自己对Linux时常有一些畏惧感,这种畏惧的由来是有些东西研究了很多次仍然研究不清楚,比如firewall就研究了很多次但现在仍不太会用,这进而导致一些只是看起来难的东西也不想去看了。systemctl就是如此。
最近经同事的提点,对systemctl有了些理解,在此记一记。
1.2 service和systemctl
是使用service还是systemctl,取决于操作系统初使化进程(即pid为1的进程)使用的是System V init还是Systemd,前者使用的服务管理命令是service后者使用的是systemctl。
总的而言Systemd在启动速度等方面较System V init都具有优势,虽然有一些反对的声音,但Systemd取代System V init已是大势所趋。更多内容可点击链接。
在新版本的CentOS7中我们可以看到也是可以使用service命令的,但这个service命令其实只是systemctl的一个脚本封装。
二、添加一个systemd服务
我们这使用nc没安装先用yum安装一下:yum install nc -y
2.1 创建简单的服务配置文件
cat > /usr/lib/systemd/system/lstestd.service << EOF [Unit] Description=it is a ls test service Documentation=man:nc After=network.target [Service] ExecStart=/usr/bin/nc -l 9998 ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=42s [Install] WantedBy=multi-user.target EOF
其中其实最主要的就是systemctl start调用的ExecStart(其值就是正常的bash命令)和systemctl stop使用的KillMode,其他随意看着填。(停止也可以用"ExecStop=/bin/kill -9 $MAINPID"这种暴力写法)
2.2 启动和停止服务
创建上边配置文件后一个systemd服务就相当于配置完了,下边直接用systemctl来启动即可。我们文件名是lstestd,即用该名称来调用即可。
# 查看服务状态
systemctl status lstestd
# 启动服务
systemctl start lstestd
# 停止服务
systemctl stop lstestd
如下图所示可以成功使用systemctl进行控制
三、systemd服务的几种情况
上边的systemd服务配置还是很简单的,事实上systemd还可以配置在服务启动前(ExecStartPre)、启动后(ExecStartPost)、停止后(ExecStopPost)等众多情况做很多事情,可自行man systemd.service查看手册进行学习。这只说自己疑惑的几种情况
3.1 systemctl enable在做什么
我们知道systemctl enable lstestd表示将lstestd服务设为开机自启动(service对应的是chkconfig lstestd on),那他到底是如何实现的呢。
man systemctl看了一下说就只是给配置文件创建了一个软件链,且在执行systemctl enable时会直接输出他做了什么,我们测试如下:
那所谓设置开机自启动,那猜测就是系统启动时会自动启动/etc/systemd/system/目录下的服务,在这目录下创建/删除软链接即能设置/f去除开机自启动。
另外要注意如果一个服务被设置为开机自启动后,再去修改服务配置文件时,需要执行一下“systemctl daemon-reload”,不然后续操作该服务会报如下错误:
Warning: lstestd.service changed on disk. Run 'systemctl daemon-reload' to reload units.这
这个命令我还不太确定是做了什么事情,因为我们对配置文件的修改已经保存了,enable也只是做个软链,那还需要额外做什么呢。
3.2 systemctl启动命令时如何给服务传递参数
日常启程序时我们常在命令行给程序传递参数,比如"nc -l 9998",那systemctl有没有类似“systemctl start lstestd -l 9998”之类的写法,能让我们在命令行给服务传递参数呢。
首先结论是systemctl是不支持通过命令行给程序动态传递参数的,折中的做法是可以使用Environment/EnvironmentFile配置变量,然后在后边的命令中就可以使用这些参数了。
直接定义变量:
Environment="ONE=one" 'TWO=two two' ExecStart=/bin/echo $ONE $TWO ${TWO}
变量定义在另外的配置文件中:
EnvironmentFile=/etc/sysconfig/testenv ExecStart=/bin/echo $ONE $TWO
/etc/sysconfig/testenv定义如下:
# define your vars like in bash file ONE=one TWO=two