在 SysV 中,我可以使用一个条件来确保应用程序不会在数据库启动并运行之前尝试启动。我给init脚本一段时间等待,一段时间后如果数据库服务仍然不可用,最后放弃。
start() {
local exec=/path/to/exec
local tries=1
[ -x $exec ] || exit 5
echo -n $"Starting $prog: "
#check communication to database
if ! [ 2>/dev/null : < /dev/tcp/$dbHost/$dbPort ]
then
while ! [ 2>/dev/null : < /dev/tcp/$dbHost/$dbPort ] && [ ! $tries -ge 5 ]
do
>&2 echo -e "Could not connect to the database on $dbHost\nWaiting 10 seconds to check database status, attempt $tries"
sleep 10
((tries++))
done
sleep 10
if ! (: < /dev/tcp/$dbHost/$dbPort ) 2>/dev/null
then
>&2 echo -e "Could not connect to the database on $dbHost aborting startup of $exec"
exit 1
fi
fi
我一直在文档和谷歌中搜索类似的场景,但没有找到任何不引用本地服务的内容。
答案1
如果您只有一项服务,具体取决于数据库的可用性,@GracefulRestart 的答案是最好的。但是,如果您有多个有此要求的服务,请创建一个所有服务都可以依赖的一次性服务Requires=
:
/etc/systemd/系统/[电子邮件受保护]
[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
我使脚本更加灵活,以防您更改或添加数据库服务器,或者端口更改,或者您想要更改每个服务级别的重试次数。如果您不需要,只需致电服务部门portopen.service
并卸下%I
零件即可。
假设您的数据库服务器已打开foobar
并且您的数据库应用程序在 上运行foobarapp.service
。进行以下更改foobarapp.service
:
# systemctl edit foobarapp.service
[在编辑器中]
[Unit]
[email protected]
[email protected]
然后重新加载systemd
并启动并启用检查:
# systemctl daemon-reload
# systemctl enable [email protected]
然后您可以foobarapp.service
随时重新启动。仅当[email protected]
成功返回时才应启动。
如果它尚不存在,则数据库应用程序服务foobarapp.service
将如下所示:
/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
答案2
您是否看过 ExecStartPre 中的systemd 服务文档?
exit 0
我建议将数据库测试放入脚本中,在成功和失败时使用它exit 1
,然后使用ExecStartPre
.然后您将使用 启动您的应用程序ExecStart
。