How can I start a systemd service only after mysql has started?

Posted in :

在 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.

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *