我有一项systemd
服务或多或少是这样的:
[Service]
ExecStart=/usr/local/bin/binary subcommand
User=my-user
Group=my-group
EnvironmentFile=/etc/my-service/config
我正在更改内容/etc/my-service/config
我应该运行daemon-reload
还是重新加载服务?
ExecReload
请注意,我的单元文件中没有指令;这会影响systemctl reload my-service
的行为吗?
答案1
也daemon-reload
不会reload
被EnvironmentFile=
您的主进程读取。
手册页表示,列出的文件EnvironmentFile=
将在进程执行前不久被读取。
- 这表明
start
或restart
将导致文件被读取。那是因为start
或restart
将执行该过程。 - 这也表明
daemon-reload
不会有任何影响,因为daemon-reload
不start
或restart
单位。 - 这还表明
reload
不会产生任何影响,因为reload
不创建主进程。它仅提供向主进程发送信号以重新加载其配置的机会。如果您没有ExecReload=
定义,则尤其如此。
一个支持实验
$ systemctl --user cat env.service
# /home/stew/.config/systemd/user/env.service
[Service]
ExecStart=/bin/bash -c "while true; do sleep 1; echo $EXAMPLE_ENV; done"
EnvironmentFile=%h/env
$ cat ~/env
EXAMPLE_ENV="Hi"
$ systemctl --user start env.service
然后我在操作过程中监视日志:
$ journalctl --user -u env.service -f
...
Feb 11 15:35:47 stewbian systemd[1108]: Started env.service.
Feb 11 15:35:48 stewbian bash[911848]: Hi
Feb 11 15:35:49 stewbian bash[911848]: Hi
然后我更改环境文件并看到输出没有变化
$ sed -i -e 's/Hi/Yo/' ~/env
...
Feb 11 15:37:13 stewbian bash[911848]: Hi
Feb 11 15:37:14 stewbian bash[911848]: Hi
Feb 11 15:37:15 stewbian bash[911848]: Hi
然后我尝试 asystemctl reload
并看到输出没有变化:
$ systemctl --user reload env.service
Failed to reload env.service: Job type reload is not applicable for unit env.service.
...
Feb 11 15:38:14 stewbian bash[911848]: Hi
Feb 11 15:38:15 stewbian bash[911848]: Hi
然后我尝试 adaemon-reload
并看到输出没有变化:
$ systemctl --user daemon-reload
...
Feb 11 15:38:46 stewbian bash[911848]: Hi
Feb 11 15:38:47 stewbian bash[911848]: Hi
然后我尝试重新启动并查看更改。
$ systemctl --user restart env.service
...
Feb 11 15:39:29 stewbian bash[911848]: Hi
Feb 11 15:39:30 stewbian bash[911848]: Hi
Feb 11 15:39:30 stewbian systemd[1108]: Stopping env.service...
Feb 11 15:39:30 stewbian systemd[1108]: Stopped env.service.
Feb 11 15:39:30 stewbian systemd[1108]: Started env.service.
Feb 11 15:39:31 stewbian bash[912531]: Yo
Feb 11 15:39:32 stewbian bash[912531]: Yo
一件有趣的事情是添加ExecReload=/bin/bash -c 'echo $EXAMPLE_ENV
到单元中。在这种情况下我得到这个:
Feb 11 15:58:24 stewbian bash[914611]: Hi
Feb 11 15:58:25 stewbian bash[914611]: Hi
Feb 11 15:58:26 stewbian systemd[1108]: Reloading env.service...
Feb 11 15:58:26 stewbian bash[914640]: Yo
Feb 11 15:58:26 stewbian systemd[1108]: Reloaded env.service.
Feb 11 15:58:26 stewbian bash[914611]: Hi
Feb 11 15:58:27 stewbian bash[914611]: Hi
所以在这里你可以看到在启动之前systemd
确实读取了,但只将新环境传递给新进程。它不会改变现有流程的环境。EnvironmentFile=
ExecReload=
我通过将这些bash
内容放入单独的脚本中进行了重试,以确保 systemd 环境变量替换在解析行期间不会影响任何内容Exec*=
...相同的结果。
支持文档
man systemd.exec
:
EnvironmentFile=
...
The files listed with this directive will be read shortly before
the process is executed (more specifically, after all processes
from a previous unit state terminated. This means you can
generate these files in one unit state, and read it with this
option in the next. The files are read from the file system of
the service manager, before any file system changes like bind
mounts take place).
man systemctl
:
reload PATTERN...
Asks all units listed on the command line to reload their
configuration. Note that this will reload the service-specific
configuration, not the unit configuration file of systemd. If you
want systemd to reload the configuration file of a unit, use the
daemon-reload command. In other words: for the example case of
Apache, this will reload Apache's httpd.conf in the web server,
not the apache.service systemd unit file.
This command should not be confused with the daemon-reload
command.
daemon-reload
Reload the systemd manager configuration. This will rerun all
generators (see systemd.generator(7)), reload all unit files, and
recreate the entire dependency tree. While the daemon is being
reloaded, all sockets systemd listens on behalf of user
configuration will stay accessible.
This command should not be confused with the reload command.
In other words: for the example case of Apache, this will reload Apache's httpd.conf in the
web server, not the apache.service systemd unit file.
This command should not be confused with the daemon-reload command.
man systemd.service
:
ExecReload=
Commands to execute to trigger a configuration reload in the
service. This argument takes multiple command lines, following
the same scheme as described for ExecStart= above. Use of this
setting is optional. Specifier and environment variable
substitution is supported here following the same scheme as for
ExecStart=.
One additional, special environment variable is set: if known,
$MAINPID is set to the main process of the daemon, and may be
used for command lines like the following:
ExecReload=kill -HUP $MAINPID
Note however that reloading a daemon by sending a signal (as with
the example line above) is usually not a good choice, because
this is an asynchronous operation and hence not suitable to order
reloads of multiple services against each other. It is strongly
recommended to set ExecReload= to a command that not only
triggers a configuration reload of the daemon, but also
synchronously waits for it to complete. For example, dbus-
broker(1) uses the following:
ExecReload=busctl call org.freedesktop.DBus \
/org/freedesktop/DBus org.freedesktop.DBus \
ReloadConfig