Systemd

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

  • February 13, 2022

我的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的行為嗎?

daemon-reload不會也reload不會EnvironmentFile=被您的主程序讀取。

手冊頁說列出的文件EnvironmentFile=將在執行該過程之前不久被讀取。

  • 這表明startrestart將導致文件被讀取。那是因為startrestart將執行該過程。
  • 這也暗示daemon-reload不會因為daemon-reload沒有startrestart單位而產生影響。
  • 這也表明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

引用自:https://unix.stackexchange.com/questions/690203