systemd 插入单元,ExecStartPre 以 root 用户身份运行,ExecStart 以自定义用户身份运行

systemd 插入单元,ExecStartPre 以 root 用户身份运行,ExecStart 以自定义用户身份运行

我有一个使用 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

相关内容