使 systemd 服务了解配置文件中的更改

使 systemd 服务了解配置文件中的更改

我有一项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不会reloadEnvironmentFile=您的主进程读取。

手册页表示,列出的文件EnvironmentFile=将在进程执行前不久被读取。

  • 这表明startrestart将导致文件被读取。那是因为startrestart将执行该过程。
  • 这也表明daemon-reload不会有任何影响,因为daemon-reloadstartrestart单位。
  • 这还表明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

相关内容