在 centos 裡,如果 service 執行順序有問題,會造成程式無法啟動,有些程式必需等 database service 先啟動後,才能執行,寫法如下:
Add After=mysql.service
to your service file (or change it to the correct service name), e.g:
[Unit]
Description=Boardies Email Server Startup Script
After=mysql.service
[Service]
ExecStart=/home/bits/EmailServer/start.email
Restart=always
[Install]
WantedBy=multi-user.target
Please note that you don’t have to put your service file into /lib/systemd/system, it is a user provided file and you should only copy it to /etc/systemd/system.
To get a list of all service files you can use systemctl list-unit-files
and determine the correct name for your database service (it is probably either mysql.service or mysqld.service)
After a lot more reading I found the solution that works for me.
I read this guide, Running Services After the Network is up. A little quote from the guide:
This will ensure that all configured network devices are up and have an IP address assigned before boot continues.
This is exactly what I wanted so I enabled this service and set the a dependency rule in the service file for crond
:
[root@srv]# systemctl enable NetworkManager-wait-online
[root@srv]# vi /lib/systemd/system/crond.service
Requires=network.target
After=syslog.target auditd.service systemd-user-sessions.service time-sync.target network.target mysqld.service
As mysqld
is still based on the old init.d
I needed to create a systemd
service as suggested here, systemctl enable differs from systemctl start:
[root@srv]# vi /lib/systemd/system/mysqld.service
[Unit]
Description=MySQL Server
After=network.target
[Service]
Type=forking
ExecStart=/etc/rc.d/init.d/mysql start
ExecStop=/etc/rc.d/init.d/mysql stop
[Install]
WantedBy=multi-user.target
[root@srv]# systemctl daemon-reload
[root@srv]# chkconfig mysql off
[root@srv]# systemctl enable mysqld
And finally setup the Apache service to startup after MySQL:
[root@srv]# vi /lib/systemd/system/httpd.service
Requires=mysqld.service
After=network.target remote-fs.target nss-lookup.target mysqld.service
This works for me at least.
I have used these commands to check it afterwards where I clearly can see that network is started up prior to at least MySQL and Apache. I though cannot see the crond
anywhere but I can see it is working in my scripts:
[root@srv]# systemd-analyze critical-chain
multi-user.target @10.510s
+ httpd.service @10.344s +165ms
+ mysqld.service @9.277s +1.065s
+ network.target @9.273s
+ network.service @8.917s +355ms
+ iptables.service @444ms +157ms
+ basic.target @443ms
[CUT]
A couple of other useful commands I used are:
# See exactly what takes how long (who to blame for the delay)
[root@srv]# systemd-analyze blame
# Check available names that can be used in the service files
[root@srv]# systemctl list-unit-files
If any one can see any better way to do this then please share.
了解一下在 [Service] 当中有哪些项目可以使用!
[Service] 部份 | |
---|---|
设置参数 | 参数意义说明 |
Type | 说明这个 daemon 启动的方式,会影响到 ExecStart 喔!一般来说,有下面几种类型 simple:默认值,这个 daemon 主要由 ExecStart 接的指令串来启动,启动后常驻于内存中。forking:由 ExecStart 启动的程序通过 spawns 延伸出其他子程序来作为此 daemon 的主要服务。原生的父程序在启动结束后就会终止运行。 传统的 unit 服务大多属于这种项目,例如 httpd 这个 WWW 服务,当 httpd 的程序因为运行过久因此即将终结了,则 systemd 会再重新生出另一个子程序持续运行后, 再将父程序删除。据说这样的性能比较好!!oneshot:与 simple 类似,不过这个程序在工作完毕后就结束了,不会常驻在内存中。dbus:与 simple 类似,但这个 daemon 必须要在取得一个 D-Bus 的名称后,才会继续运行!因此设置这个项目时,通常也要设置 BusName= 才行!idle:与 simple 类似,意思是,要执行这个 daemon 必须要所有的工作都顺利执行完毕后才会执行。这类的 daemon 通常是开机到最后才执行即可的服务!比较重要的项目大概是 simple, forking 与 oneshot 了!毕竟很多服务需要子程序 (forking),而有更多的动作只需要在开机的时候执行一次(oneshot),例如文件系统的检查与挂载啊等等的。 |
EnvironmentFile | 可以指定启动脚本的环境配置文件!例如 sshd.service 的配置文件写入到 /etc/sysconfig/sshd 当中!你也可以使用 Environment= 后面接多个不同的 Shell 变量来给予设置! |
ExecStart | 就是实际执行此 daemon 的指令或脚本程序。你也可以使用 ExecStartPre (之前) 以及 ExecStartPost (之后) 两个设置项目来在实际启动服务前,进行额外的指令行为。 但是你得要特别注意的是,指令串仅接受“指令 参数 参数…”的格式,不能接受 <, >, >>, |, & 等特殊字符,很多的 bash 语法也不支持喔! 所以,要使用这些特殊的字符时,最好直接写入到指令脚本里面去!不过,上述的语法也不是完全不能用,亦即,若要支持比较完整的 bash 语法,那你得要使用 Type=oneshot 才行喔! 其他的 Type 才不能支持这些字符。 |
ExecStop | 与 systemctl stop 的执行有关,关闭此服务时所进行的指令。 |
ExecReload | 与 systemctl reload 有关的指令行为 |
Restart | 当设置 Restart=1 时,则当此 daemon 服务终止后,会再次的启动此服务。举例来说,如果你在 tty2 使用文字界面登陆,操作完毕后登出,基本上,这个时候 tty2 就已经结束服务了。 但是你会看到屏幕又立刻产生一个新的 tty2 的登陆画面等待你的登陆!那就是 Restart 的功能!除非使用 systemctl 强制将此服务关闭,否则这个服务会源源不绝的一直重复产生! |
RemainAfterExit | 当设置为 RemainAfterExit=1 时,则当这个 daemon 所属的所有程序都终止之后,此服务会再尝试启动。这对于 Type=oneshot 的服务很有帮助! |
TimeoutSec | 若这个服务在启动或者是关闭时,因为某些缘故导致无法顺利“正常启动或正常结束”的情况下,则我们要等多久才进入“强制结束”的状态! |
KillMode | 可以是 process, control-group, none 的其中一种,如果是 process 则 daemon 终止时,只会终止主要的程序 (ExecStart 接的后面那串指令),如果是 control-group 时, 则由此 daemon 所产生的其他 control-group 的程序,也都会被关闭。如果是 none 的话,则没有程序会被关闭喔! |
RestartSec | 与 Restart 有点相关性,如果这个服务被关闭,然后需要重新启动时,大概要 sleep 多少时间再重新启动的意思。默认是 100ms (毫秒)。 |
最后,再来看看那么 Install 内还有哪些项目可用?
[Install] 部份 | |
---|---|
设置参数 | 参数意义说明 |
WantedBy | 这个设置后面接的大部分是 *.target unit !意思是,这个 unit 本身是附挂在哪一个 target unit 下面的!一般来说,大多的服务性质的 unit 都是附挂在 multi-user.target 下面! |
Also | 当目前这个 unit 本身被 enable 时,Also 后面接的 unit 也请 enable 的意思!也就是具有相依性的服务可以写在这里呢! |
Alias | 进行一个链接的别名的意思!当 systemctl enable 相关的服务时,则此服务会进行链接文件的创建!以 multi-user.target 为例,这个家伙是用来作为默认操作环境 default.target 的规划, 因此当你设置用成 default.target 时,这个 /etc/systemd/system/default.target 就会链接到 /usr/lib/systemd/system/multi-user.target 啰! |
如果 Type 設成 forking, service可能會產生下面的錯誤:
service start operation timed out. Terminating.
解法:
you made the service type forking
, but this service does not fork. It just runs directly. Thus systemd waited five minutes for the program to daemonize itself, and it never did. The correct type for such a service is simple
.
It seems like Nagios is not properly forking into background -d
option, what systemd expects here due to type=forking
.
So systemd counts a non-fork as a timeout during start.