How to start services in certain order with Systemd?
Have been reading a bunch of documentation to figure this one out.
By the way, this also includes the SysV startup scripts (which are called by systemd).
So, in this below example (real situation), I have Docker that needs ocfs2 filesystem which runs on top of DRBD.
Default startup configuration was not quite ok because docker almost always started first and ocfs2 was started in the same time with drbd and failed to mount the ocfs2 filesystem.
The error was: mount.ocfs2: I/O error on channel while opening device /dev/drbd0
The main trick is: you do not start services in a certain order but you "ask" your main service to start the others. Bear with me.
1. Disable startup for ocfs2 and drbd
root@candy:~# systemctl disable drbd.service drbd.service is not a native service, redirecting to systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable drbd root@candy:~# systemctl disable ocfs2.service Synchronizing state of ocfs2.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable ocfs2 Removed /etc/systemd/system/multi-user.target.wants/ocfs2.service.
2. Add drbd.service as requirement for ocfs2.service
NOTE: copy /lib/systemd/system/ocfs2.service to /etc/systemd/system/ocfs2.service and edit the one from /etc and recommended by systemd docs.
The edited lines should be as follows:
root@candy:~# egrep "^Requires|^After" /etc/systemd/system/ocfs2.service Requires=o2cb.service drbd.service After=o2cb.service drbd.service
3. Add ocfs2.service as requirement for docker.service
Please do not forget about the note from point 2.
root@candy:~# egrep "^Requires|^After" /etc/systemd/system/docker.service After=network-online.target firewalld.service containerd.service ocfs2.service Requires=docker.socket ocfs2.service
3. Make sure docker.service is enabled and reloaded
root@candy:~# systemctl daemon-reload root@candy:~# systemctl enable docker.service Synchronizing state of docker.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable docker Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /etc/systemd/system/docker.service.
Now what will happen is:
- docker is configured to start at boot but it needs ocfs2;
- ocfs2 is not configured to start at boot, is stated by docker but it needs drbd;
- drbd is also not configured to start at boot but is started by ocfs2.
And with this chain you have them in the needed order.
Enjoy!
PS: as bonus command, systemd-analyze is showing you now what docker-service needs in order to start:
root@candy:~# systemd-analyze critical-chain docker.service The time after the unit is active or started is printed after the "@" character. The time the unit takes to start is printed after the "+" character. docker.service +1.796s └─ocfs2.service @17.202s +8.290s └─drbd.service @5.478s +11.722s └─ssh.service @4.242s +1.234s └─network.target @4.230s └─networking.service @3.982s +245ms └─apparmor.service @3.720s +251ms └─local-fs.target @3.718s └─docker-btrfs.mount @26.536s └─docker.mount @3.097s +7ms └─dev-mapper-dockervg\x2ddocker.device @3.095s