How do you use systemd to ensure remote database is available
@GracefulRestart's answer is the best if you only have one service depending on the availability of the database. However, if you have multiple services that have this requirement, make a oneshot service that all of the services can then have a Requires=
dependency to:
/etc/systemd/system/[email protected]
[Unit]
Description=Checks database availability on %I
After=network.target
Requires=network.target
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/path/to/portopen.sh %I
[Install]
WantedBy=default.target
/path/to/portopen.sh
#!/bin/bash
dbhost=${1:-localhost}
dbport=${2:-5678}
maxtries=${3:-5}
wait=${4:-10}
tries=1
# Check communication to database
while ! [ 2>/dev/null : < /dev/tcp/$dbhost/$dbport ]; do
echo "Unable to connect to database on $dbhost TCP/$dbport (attempt $tries): retrying in $wait seconds" >&2
(( tries++ ))
if [[ $tries -le $maxtries ]]; then
sleep $wait
else
echo "Unable to connect to database on $dbhost TCP/$dbport: aborting"
exit 1
fi
done
I made the script a bit more flexible in case you change or add database servers, or the port changes, or you want to change the number of retries on a per-service level. If you don't need that, just call the service portopen.service
and remove the %I
parts.
Let's say your database server is on foobar
and your database application runs on foobarapp.service
. Make the following changes to foobarapp.service
:
# systemctl edit foobarapp.service
[in editor]
[Unit]
[email protected]
[email protected]
Then reload systemd
and start and enable the check:
# systemctl daemon-reload
# systemctl enable [email protected]
You can then restart foobarapp.service
whenever you want. It should only start if [email protected]
returns successfully.
If it doesn't already exist, the database application service foobarapp.service
would then look like this:
/etc/systemd/system/foobarapp.service
[Unit]
Description=Foobar database application
# Add any other dependencies here
[email protected]
[email protected]
[Service]
# If it is a daemon, use "forking" instead
Type=simple
ExecStart=/path/to/exec
[Install]
WantedBy=default.target
Have you looked at ExecStartPre in the systemd service documentation?
I would suggest putting your database test in a script, have it use exit 0
on success and exit 1
on failure and then run it with ExecStartPre
. You would then start your application using ExecStart
.