在 systemd 执行守护进程之前,我需要创建或更改符号链接的目标。守护进程将其标准输出重定向到此符号链接,并随之重定向到每个启动的守护进程的特殊文件中。这就是想法。我设置了名为“test_start.service”的服务单元文件:
[Unit]
Description=Test Server
After=network-online.target test_start.socket
Requires=network-online.target test_start.socket
[Service]
User=test1
Group=test1
Type=simple
ExecStartPre=/bin/bash /etc/testServer/Debug/makeOutfile.sh
ExecStart=/etc/testServer/Debug/testServer
StandardInput=socket
StandardOutput=file:/etc/testServer/Debug/test_outLink
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
bash 脚本“/etc/testServer/Debug/makeOutfile.sh”如下所示:
#!/usr/bin/env bash
timeStamp=$(date +%y-%m-%d_%Hh%Mm%Ss)
myfolder="/etc/testServer/Debug"
# create new logfile
touch $myfolder/started_$timeStamp
# remove old symlink if exists (owned by test1)
if [ -h $myfolder/test_outLink ]; then
rm $myfolder/test_outLink
fi
# create new symlink
ln -s $myfolder/started_$timeStamp $myfolder/test_outLink
它在某些情况下有效。如果符号链接存在并且它指向的文件也存在,那么一切都很好。bash 脚本“makeOutfile.sh”通过终端运行以进行测试,并通过 systemd 服务启动。
但:
如果指向的文件(名称:“started_atSomeDate”)不存在(因为它同时被某人删除),则脚本的终端调用按预期工作,但启动 systemd 服务将添加一个由 root 拥有的附加文件和组具有原始旧文件名的根:“started_atSomeDate”。
那是从哪里来的?
如果旧符号链接“test_outLink”不存在(因为它同时被某人删除),脚本的终端调用按预期工作,但启动 systemd 服务会将新创建的“test_outLink”添加为 root 拥有的常规文件使用组 root 并且服务无法启动。
这里出现了严重错误,虽然 systemd 服务单元用户和组是 test1,但 root 在这里混在一起。谁能解释一下?我究竟做错了什么?
我的建议是你应该使用一个 shell 脚本来设置日志文件并使用适当的重定向执行测试服务器,从而绕过
StandardOutput=
对你的情况不起作用的 systemd 设置。像这样创建一个 bash 脚本
/etc/testServer/Debug/runTestServer.sh
:与您的原始脚本的唯一区别
makeOutfile.sh
是,此脚本testServer
使用适当的重定向执行,以将其标准输出发送到您刚刚设置的日志文件。它还用于
exec
确保 shell 脚本不会被保留和替换testServer
(因此 systemd 将知道服务的主要进程是什么。)在您的单元文件中,删除
ExecStartPre=
和 并将其StandardOutput=
替换为ExecStart=
:(或者
/bin/bash
也可以调用脚本,但只要脚本设置了可执行位就没有必要。)通过这样的脚本设置您的服务器,您甚至可以完全绕过符号链接并直接重定向到最终的
started_$timeStamp
日志文件。我没有直接查看 systemd 代码,文档也不清楚具体之间的交互
StandardOutput=
......ExecStartPre=
但是 systemd 执行步骤的顺序肯定存在问题(以及哪个进程执行它们,这导致不同的权限/所有权),所以我对你报告的结果并不感到惊讶。我想,无论如何,我的建议是使用单个包装器执行器脚本来简化它,因此希望这可以解决您的问题。