概括:有没有办法确保 NFS 服务器在能够正确解析指定的客户端机器名称之前不会由 systemd 启动/etc/exports
?
问题描述:我发现服务器(运行 16.10)重新启动后,NFS 共享无法正常使用。客户端收到“服务器拒绝访问”错误,直到在服务器上手动运行exportfs -ra
或service nfs-server restart
。此后,一切都按预期运行。
服务器/etc/exports
仅包含:
/mnt/raidarray clientmachine(rw)
其中clientmachine
是本地网络上 NFS 客户端计算机的主机名。
问题识别:(以下)的输出systemctl status nfs-server
清楚地表明了问题:在 NFS 服务器启动时无法解析客户端的名称。
● nfs-server.service - NFS server and services
Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled
Active: active (exited) since Tue 2017-01-17 16:47:38 CST; 26min ago
Main PID: 1520 (code=exited, status=0/SUCCESS)
Tasks: 0 (limit: 4915)
CGroup: /system.slice/nfs-server.service
Jan 17 16:47:38 servermachine exportfs[1511]: exportfs: Failed to resolve clientmachine
Jan 17 16:47:38 servermachine systemd[1]: Started NFS server and services.
NetworkManager-wait-online.service
已启用,我已经明白用于确保network.target
(取决于哪个)在满足nfs-server
之前不会满足。network-online.target
没有帮助的事情:
以防我误解了什么
NetworkManager-wait-online.service
,我尝试在 中添加显式的After=network-online.target
andWants=network-online.target
。nfs-server.service
这并没有解决任何问题。我看到 中出现了新的依赖项systemctl list-dependencies
,但名称解析在启动时仍然失败。因此,这似乎network-online.target
不能保证主机名解析可以发生。一些谷歌搜索表明,要求
nss-lookup.target
可以确保网络分辨率可用,但将其添加为Wants
和/或After
依赖项nfs-server.service
也不能解决问题!添加
Wants
and/orAfter
依赖systemd-resolved.service
而不是nss-lookup.target
也不能解决问题。
添加所有这些依赖项后,nfs-server
在启动过程的很晚的时候启动(就在桌面登录之前),但仍然无法解析主机。根据systemd-analyze plot
,似乎nmbd
此时卡住了,但我不知道这是否相关。
配置信息:这是 kubuntu 16.10 的桌面版本,基本上是全新安装。
NetworkManager.service
已启用并且systemd-networkd.service
已禁用 - 我没有更改默认设置。
以下是NetworkManager-wait-online
服务定义:
[Unit]
Description=Network Manager Wait Online
Documentation=man:nm-online(1)
Requisite=NetworkManager.service
After=NetworkManager.service
Before=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/nm-online -s -q --timeout=30
RemainAfterExit=yes
[Install]
WantedBy=network-online.target
作为一种解决方法,我可以将 IP 地址而不是主机名硬编码到/etc/exports
或中/etc/hosts
,但这似乎有些脆弱。 有更好的答案吗?
编辑-更新:按照下面@muru的建议,我尝试编写一个脚本来等待解析主机名——只是为了看看需要多长时间。我的脚本在systemd-resolved
启动后必须等待数十秒才能真正解析主机。这非常奇怪。我想知道这是否实际上是本地网络问题?听起来也许需要硬编码(并且可能是自动更新,正如@mark-stosberg 所建议的那样)/etc/exports
或/etc/hosts
文件。
答案1
根据@muru 的评论,我编写了一个 python 脚本来等待 DNS 解析:
import socket
import time
import itertools
TIMEOUT = 30
HOSTS = ['stanford.edu', 'google.com', 'example.com']
def main():
hosts = itertools.cycle(HOSTS)
t0 = time.time()
for host in hosts:
t = time.time()
elapsed = t - t0
if elapsed > TIMEOUT:
break
try:
socket.getaddrinfo(host, None, proto=socket.IPPROTO_TCP)
print('Resolved {} at t = {}'.format(host, elapsed))
break
except socket.gaierror:
print('Could not resolve {} at t = {}'.format(host, elapsed))
time.sleep(0.25)
t = time.time()
if __name__ == '__main__':
main()
我将该脚本保存为/etc/systemd/system/nfs-server.service.d/wait_for_dns.py
(必须先创建父目录),然后运行sudo systemctl edit --full nfs-server
,并在其他 ExecStartPre 行之前添加以下内容:
ExecStartPre=/usr/bin/python3 /etc/systemd/system/nfs-server.service.d/wait_for_dns.py
效果不错,尽管感觉有点黑客化,而且可以在很多方面改进。(在这种情况下,我最终放弃了 NFS;它带来的痛苦比它的价值更大。)
答案2
就您要用 做什么而言systemd
,您已经尝试做最好的事情,即将您的服务设置为在 之后启动network-online
。我读了很多systemd
问题,其他人也报告了这样做时网络无法完全在线的问题。
/etc/exports
我建议按照您的建议输入 IP 地址/etc/hosts
。这可以简化启动过程中重要的磁盘安装任务。
为了使系统更加强大,您可以使用 cron 作业或 systemd 计时器定期检查相关主机的 DNS 是否已更改。如果已更改,则自动/etc/hosts
使用新值进行更新。
答案3
我在 ubuntu 16.04.03 LTS 安装中遇到了同样的问题。
重启后,exportfs 无法正常运行,因此 nfs-kernel-server 无法正常启动。
我尝试在 /etc/init.d/nfs-kernel-server 中的启动案例中添加 sleep ,但这没有帮助。
我还尝试了一些提示https://discourse.osmc.tv/t/nfs-kernel-server-wont-start-on-boot/5936/7
我最终通过在 /etc/rc.local 中添加以下行解决了该问题
systemctl restart nfs-kernel-server
答案4
今天遇到了同样的问题(我使用的是 AlmaLinux 8.6),并使用 systemctl edit nfs-server 进行了修复:
[Unit]
Requires=network.target network-online.target
After=network.target network-online.target