我在虚拟机中运行 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 应该不会再在系统启动时无法启动。