我可以让 Apache 仅在系统从 DHCP 获取其地址后启动吗?

我可以让 Apache 仅在系统从 DHCP 获取其地址后启动吗?

我在虚拟机中运行 Ubuntu,目的是进行本地 Wordpress 安装,需要进行一些本地测试。

为此,我在 VirtualBox 中将此机器的网络模式配置为桥接,将我的家庭路由器配置为始终将相同的 IP 地址(192.168.0.101)租用给此 VM 的 MAC 地址,并将 Apache 配置为监听此地址etc/apache2/ports.conf

Listen 192.168.0.101:80

<IfModule ssl_module>
        Listen 192.168.0.101:443
</IfModule>

<IfModule mod_gnutls.c>
        Listen 192.168.0.101:443
</IfModule>

不幸的结果是 Apache 经常拒绝在系统启动时启动:

m@m-VirtualBox:~$ sudo systemctl status apache2
[sudo] password for m: 
× apache2.service - The Apache HTTP Server
     Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Fri 2021-10-22 16:12:19 CEST; 28s ago
       Docs: https://httpd.apache.org/docs/2.4/
    Process: 681 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)
        CPU: 19ms

paź 22 16:12:19 m-VirtualBox systemd[1]: Starting The Apache HTTP Server...
paź 22 16:12:19 m-VirtualBox apachectl[701]: (99)Cannot assign requested address: AH00072: make_sock: could not bind to address 192.168.0.101:80
paź 22 16:12:19 m-VirtualBox apachectl[701]: no listening sockets available, shutting down
paź 22 16:12:19 m-VirtualBox apachectl[701]: AH00015: Unable to open logs
paź 22 16:12:19 m-VirtualBox apachectl[681]: Action 'start' failed.
paź 22 16:12:19 m-VirtualBox apachectl[681]: The Apache error log may have more information.
paź 22 16:12:19 m-VirtualBox systemd[1]: apache2.service: Control process exited, code=exited, status=1/FAILURE
paź 22 16:12:19 m-VirtualBox systemd[1]: apache2.service: Failed with result 'exit-code'.
paź 22 16:12:19 m-VirtualBox systemd[1]: Failed to start The Apache HTTP Server.

我总是可以用手动启动 Apache sudo systemctl start apache2,然后 Apache 就会成功启动。

让 Apache2 监听127.0.0.1而不是监听192.168.0.101也会让 Apache 在系统启动时成功启动,而不会出现如上所示的错误。

因此我怀疑问题可能是 Apache 在 DHCP 完成其工作之前尝试启动。Apache 尝试侦听192.168.0.101,但机器尚未分配此地址,因此 Apache 被拒绝并出错。

为了尝试解决此问题并检查我的猜测是否正确,我想以某种方式将 apache 设置为仅在 DHCP 客户端完成后启动。这可能吗?如何实现?

答案1

之前有一个热心用户的回答(遗憾的是,现在已经被删除了),我已经忘记他的昵称了几乎正确的。

建议修改该/lib/systemd/system/apache2.service文件以使其依赖network-online.target于默认值network.target,或者更好的是,添加第二个文件来使用此修改来/lib/systemd/system调用。my-apache2.service根据文档,这是确保服务仅在网络真正启动时启动的正确方法

虽然这种方法可行,但问题在于的内容/lib不应被编辑,而/etc/systemd/system应被用于此目的。(是的,我链接到的这个答案涉及 Ubuntu 以外的系统,但在 Ubuntu 上阅读man 7 file-hierarchy显示man 5 systemd.unit了同样的事情)。

第二个问题是,根据我的经验,尝试运行 Apache2 两次会导致问题。

为了解决这两个问题,我之前的回答建议在 中创建一个冲突服务/etc/systemd/system。然而,这太复杂了,无法解决上述一些问题,也就是说,它不是面向未来的:.service上游作者对原始文件所做的更改不会自动合并到我们的新.service文件中。

正确的解决方案是创建一个插入文件,After为原始文件添加新的依赖项apache2.service,如 所述man 5 systemd.unit。为此,需要输入以下命令:

# systemctl edit apache2.service

(记录在 中man 1 systemctl

...编辑器打开后,需要输入以下内容之间### Anything between here and the comment below... 和...### Lines below this comment行:

[Unit]
After=network-online.target

并保存新文件。

请注意,man 5 systemd.unit这不会替换服务原有的 After 依赖项;相反,这会为已经存在的依赖项添加新的依赖项。

供参考,以下是原文内容/lib/systemd/system/apache2.service

[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=https://httpd.apache.org/docs/2.4/

[Service]
Type=forking
Environment=APACHE_STARTED_BY_SYSTEMD=true
ExecStart=/usr/sbin/apachectl start
ExecStop=/usr/sbin/apachectl graceful-stop
ExecReload=/usr/sbin/apachectl graceful
KillMode=mixed
PrivateTmp=true
Restart=on-abort

[Install]
WantedBy=multi-user.target

从现在开始,Apache2 应该不会再在系统启动时无法启动。

相关内容