How to ensure that there is a delay before a servi

2020-05-16 13:58发布

问题:

I am having a service that depends on Cassandra coming up gracefully and the cluster being up and ready.

To ensure that the dependency order is met, I have the following unit file

[Unit]
Requires=cassandra.service
After=cassandra.service

[Service]
Environment=JAVA_HOME=/usr/java/jre
ExecStart=@bringup.instance.path@/webapps/bringup-app/bin/bringup
TimeoutStartSec=0
ExecStop=
PIDFile=@bringup.instance.path@/logs/bringup.pid
Restart=always

[Install]
WantedBy=multi-user.target

How do I ensure that the bringup-app process waits for 30 seconds before it attempts to start up? Currently although it is started after Cassandra, I have noticed that the Cassandra cluster is not up yet and hence any attempt from the bringup-app to connect to Cassandra as part of startup fails.

I therefore want to add a delay. Is that possible via the unit file?

回答1:

You can run the sleep command before your ExecStart with ExecStartPre :

[Service]
ExecStartPre=/bin/sleep 30


回答2:

You can create a .timer systemd unit file to control the execution of your .service unit file.

So for example, to wait for 1 minute after boot-up before starting your foo.service, create a foo.timer file in the same directory with the contents:

[Timer]
OnBootSec=1min

It is important that the service is disabled (so it doesn't start at boot), and the timer enabled, for all this to work (thanks to user tride for this):

systemctl disable foo.service
systemctl enable foo.timer

You can find quite a few more options and all information needed here: https://wiki.archlinux.org/index.php/Systemd/Timers



回答3:

Instead of editing the bringup service, add a post-start delay to the service which it depends on. Edit cassandra.service like so:

ExecStartPost=/bin/sleep 30

This way the added sleep shouldn't slow down restarts of starting services that depend on it (though does slow down its own start, maybe that's desirable?).



回答4:

This answer on super user I think is a better answer. From https://superuser.com/a/573761/67952

"But since you asked for a way without using Before and After, you can use:

Type=idle

which as man systemd.service explains

Behavior of idle is very similar to simple; however, actual execution of the service program is delayed until all active jobs are dispatched. This may be used to avoid interleaving of output of shell services with the status output on the console. Note that this type is useful only to improve console output, it is not useful as a general unit ordering tool, and the effect of this service type is subject to a 5s time-out, after which the service program is invoked anyway. "



回答5:

The systemd way to do this is to have the process "talk back" when it's setup somehow, like by opening a socket or sending a notification (or a parent script exiting). Which is of course not always straight-forward especially with third party stuff :|

You might be able to do something inline like

ExecStart=/bin/bash -c '/bin/start_cassandra &; do_bash_loop_waiting_for_it_to_come_up_here'

or a script that does the same. Or put do_bash_loop_waiting_for_it_to_come_up_here in an ExecStartPost

Or create a helper .service that waits for it to come up, so the helper service depends on cassandra, and waits for it to come up, then your other process can depend on the helper service.

(May want to increase TimeoutStartSec from the default 90s as well)



标签: systemd