在我重新加载并重新启动服务之前,SystemD 不会运行 ExecStartPre

在我重新加载并重新启动服务之前,SystemD 不会运行 ExecStartPre

我正在覆盖/usr/lib/systemd/system/docker.service启动脚本以使用环境文件扩展它。我已经定义了我的配置文件,/etc/systemd/system/docker.service.d/docker.conf如下所示:

test -d /etc/systemd/system/docker.service.d || \
    mkdir /etc/systemd/system/docker.service.d

cat > /etc/systemd/system/docker.service.d/docker.conf <<EOF
[Service]
EnvironmentFile=/etc/sysconfig/docker
ExecStartPre=-/usr/local/sbin/generate-docker-config
ExecStart=
ExecStart=/usr/bin/docker daemon -H fd:// --dns=\${LOCAL_IPV4}
EOF

systemctl daemon-reload

我正在运行上面的脚本包装机AMI 的构建步骤。

当我启动 AMI 时,我看到 SystemD 中有关 Docker 服务的以下状态输出:

● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/docker.service.d
           └─docker.conf
   Active: active (running) since Mon 2016-03-28 21:16:11 UTC; 6min ago
     Docs: https://docs.docker.com
 Main PID: 858 (docker)
   CGroup: /system.slice/docker.service
           ├─ 858 /usr/bin/docker daemon -H fd:// --dns=10.224.4.178 --log-driver=syslog --log-opt tag={{.ImageName}}

ExecStartPre如输出所示,它尚未运行 my 。如果我执行以下操作,我看到它现在已经运行了启动脚本:

# systemctl daemon-reload && systemctl restart docker.service && \
    systemctl status docker.service
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/docker.service.d
           └─docker.conf
   Active: active (running) since Mon 2016-03-28 22:05:24 UTC; 24ms ago
     Docs: https://docs.docker.com
  Process: 1873 ExecStartPre=/usr/local/sbin/generate-docker-config (code=exited, status=0/SUCCESS)
 Main PID: 1876 (docker)
   CGroup: /system.slice/docker.service
           └─1876 /usr/bin/docker daemon -H fd:// --dns=10.224.4.178 --log-driver=syslog --log-opt tag={{.ImageName}}

ExecStartPre请注意它现在如何在状态输出中显示?

除了daemon-reload导致 SystemD 加载和运行新的服务配置文件和ExecStartPre脚本之外,我还应该在 Packer 构建中运行一个命令吗?我应该只使用restartPacker 构建中的服务,还是有更好、更适合该问题的解决方案?

注意:我的脚本需要可用于 EC2 实例标签的ExecStartPre网络。 curlDocker 服务文件确实指定了After=network.target docker.socket,所以我假设它将在网络启动后运行。

答案1

嗯,这是预期的行为。如果您打算在覆盖 docker 单元文件后重新启动 docker 服务,则应该在脚本中调用systemctl restart docker.serviceafter 。systemctl daemon-reload如果您还想仅在已运行的情况下重新启动 dokett,请改为调用systemctl try-restart docker.service

命令的目的systemctl daemon-reload是告诉systemd守护进程重新加载其所有配置、重新加载单元文件并重新生成服务依赖关系树。但是,即使磁盘上的单元文件发生更改,它也不会影响系统中的任何其他服务。

答案2

假设网络“在线”后network.service并不是 100% 可靠。这就是为什么有一个network-online.target.

如果您依赖于curl并且希望在服务启动之前绝对确定网络已启动,DNS工作等,那么将其添加到您的docker.conf可能会有所帮助...

[Unit]
After=network-online.target

...并且由于您正在执行所有这些启动后操作,为了让新功能ExecStartPre正常工作,那么您应该在 Packer 构建脚本中添加systemctl daemon-reload && systemctl restart docker.service或。systemctl stop docker.service && systemctl daemon-reload && systemctl start docker.service后者最为可靠。

在修改和daemon-reload完成之前停止服务将确保整个单元按指定重新加载。我可以在您提供的输出的第三位中看到ExecStartfordocker.service确实不是包含您在 Packer 构建脚本中指定的参数。这是因为systemctl restart docker.service(与停止、守护进程重新加载和启动)。

相关内容