我有一个使用 systemd 运行的 Web 服务,该服务由其自己的用户运行,我想执行一些 ExecStartPre 命令,但以 root 用户身份运行。更详细地说:
即 /lib/systemd/system/webservice.service
[Unit]
Wants=network-online.target
After=network-online.target
[Service]
EnvironmentFile=/etc/default/web
Group=webuser
Type=simple
Restart=on-failure
WorkingDirectory=/usr/share/web
RuntimeDirectory=web
RuntimeDirectoryMode=0750
ExecStart=/usr/sbin/web --config=/etc/web/config.ini
[Install]
WantedBy=multi-user.target
我想要一个嵌入式服务,它从 Web 资源中获取 config.ini 文件
即 /etc/systemd/system/web.service.d/local.conf
[Service]
PermissionsStartOnly=true
RestartSec=5
EnvironmentFile=/etc/environment
ExecStartPre=+/usr/bin/curl http://some.url --output /etc/web/config.ini
ExecStartPre=+chown web:web /etc/web/config.ini
上述配置不起作用,因为我的服务在启动时冻结,且日志中没有任何消息。有什么方法可以让这样的事情正常工作吗?
答案1
我认为您的 systemd 设置是正确的。如果启动服务时终端挂起,那么我怀疑命令ExecStartPre
没有退出。
我在 Ubuntu 20.04 服务器上以 root 身份运行以下命令来测试类似的服务设置。
为该服务创建一个用户。
useradd --system myservice
为服务创建一个脚本,以记录运行脚本的用户身份并循环。
cat <<'EOF' > /usr/local/bin/myservice.sh
#!/usr/bin/env bash
# first argument is loop count, defaults to infinite
i=${1:--1}
while :; do
date >> ${RUNTIME_DIRECTORY:-/tmp}/run.log
whoami >> ${RUNTIME_DIRECTORY:-/tmp}/run.log
(( --i == 0 )) && break
sleep ${SLEEP:-60}
done
EOF
添加服务文件和覆盖文件。
cat <<EOF > /etc/systemd/system/myservice.service
[Unit]
Description=My Service
[Service]
EnvironmentFile=-/etc/default/myservice
Type=simple
User=myservice
Group=myservice
Restart=on-failure
RuntimeDirectory=myservice
RuntimeDirectoryMode=0750
ExecStart=/bin/bash /usr/local/bin/myservice.sh
EOF
mkdir -p /etc/systemd/system/myservice.service.d/
cat <<EOF > /etc/systemd/system/myservice.service.d/override.conf
[Service]
PermissionsStartOnly=true
ExecStartPre=/bin/bash /usr/local/bin/myservice.sh 1
ExecStartPre=chown myservice.myservice /run/myservice/run.log
EOF
systemctl daemon-reload
启动服务
systemctl start myservice.service
结果符合预期。run.log
文件显示脚本以用户身份运行一次,root
然后继续以myservice
用户身份运行,直到服务停止。
root@ubuntu:~# ls -al /run/myservice/
total 4
drwxr-x--- 2 myservice myservice 60 Feb 27 18:23 .
drwxr-xr-x 30 root root 1080 Feb 27 18:23 ..
-rw-r--r-- 1 myservice myservice 73 Feb 27 18:23 run.log
root@ubuntu:~# cat /run/myservice/run.log
Sun Feb 27 18:23:14 UTC 2022
root
Sun Feb 27 18:23:14 UTC 2022
myservice
Sun Feb 27 18:24:14 UTC 2022
myservice
我确实发现,如果ExecStartPre
命令进入循环,则在启动服务时终端似乎会挂起。这可以解释为什么您认为服务冻结了。该ExecStartPre
命令可能仍在运行或可能无法完成。
其他说明
- 我发现使用或
PermissionsStartOnly=true
都与以 root 身份ExecStartPre=+...
运行脚本具有相同的效果ExecStartPre
。