我的问题与这个问题:
在一些 Bash 脚本中我发现了这个代码片段:
...
if [ -e /etc/debian_version ]
then ipv4_localhost_re="127\.0\.1\.1"
else ipv4_localhost_re="127\.0\.0\.1"
fi
sed -i "s/^\($ipv4_localhost_re\(\s.*\)*\s\).*$/\1${name}/" /etc/hosts
sed -i "s/^\(::1\(\s.*\)*\s\).*$/\1${name}/" /etc/hosts
...
我想知道这编辑主机名的方法对于所有其他 Linux 发行版是否仍然正确,以及这些其他发行版是否以及如何处理最初报告为2005 年的 Debian Bug并导致了127.0.1.1
解决方法的引入,该解决方法似乎至今仍在 Debian、Ubuntu 等中使用,但在 Fedora、SuSE 和许多其他系统中却没有使用(如果我的研究正确的话)。
总结一下:你知道有哪个 Linux 发行版是不是
基于Debian或者已经没有/etc/debian_version
文件了但是仍然采用这个127.0.1.1
解决方案?
答案1
这是为了区分主机名和“localhost.localdomain”,因为它们可能会在没有已知固定 IP 地址的主机上混淆。
本地主机是 127.0.0.1,但保留的环回 IPv4 空间中有 1670 万个 IP(127.*.*.*
从 127.0.0.1 到 127.255.255.255 的所有 IP,如跨域路由127.0.0.0/8);该空间内的所有 IP 都以相同的方式解析。
您的链接Debian 错误 316099添加此变更日志项网络配置1.1.3(2005):
如果 /etc/hosts 中没有可以与系统主机名(即命令返回的主机名
hostname
)关联的永久 IP 地址,则将其与地址 127.0.1.1 而不是 127.0.0.1 关联。将系统主机名与后者关联会产生不良影响,使“localhost.localdomain”成为与系统主机名关联的规范主机名。也就是说,hostname --fqdn
返回“localhost.localdomain”。
您找到的脚本正在修改存储在 中的系统名称/etc/hosts
,其密钥 IP 根据我们刚刚确定的 Linux 发行版而不同。它的实现有点混乱,但它应该可以工作,将每个 /etc/hosts 条目的 IPv6 和发行版首选的 localhost IPv4 交换为新主机名,并将结果保存在原始主机名之上。
请注意,没有备份,如果该 IP 有其他映射,它们可能会被覆盖。它假设系统名称是这些行的最后一列,这可能是也可能不是。例如,127.0.1.1 home my-box-oldname localhost
将变成127.0.1.1 home my-box-oldname my-box-newname
,您将丢失localhost
。
我曾经有过/etc/hosts
在同一行中有多个定义的不好经历,所以在我的一个系统上,这可能会导致(修复此错误之前) 在:
127.0.0.1 localhost
127.0.0.1 my-box-oldname
127.0.0.1 alternate-name1
127.0.0.1 alternate-name2
变得无益
127.0.0.1 my-box-newname
127.0.0.1 my-box-newname
127.0.0.1 my-box-newname
127.0.0.1 my-box-newname
我无法回答其他发行版是否也采用了这一举措,但/etc/debian_version
基于一个值得怀疑的假设,搜索确实似乎有点不匹配。我个人更喜欢明确搜索/etc/hosts
旧主机名。
考虑用这个直接替换你提供的代码片段(它也解决了我之前的两个抱怨):
oldname="$(hostname)" # though I'm guessing the script has this value already
awk -v oldname="${oldname}" -v name="${name}" '
/^127\.|^[0:]*::1[[:space:]]/ {
for (i=2; i<=NF; i++) if ($i == oldname) $i = name
}
{ print }
' /etc/hosts > /etc/hosts.new
if diff -q /etc/hosts /etc/hosts.new >/dev/null; then
rm /etc/hosts.new
else
cp -p /etc/hosts "/etc/hosts.$(date +%Y%m%d)" && mv /etc/hosts.new /etc/hosts
fi
/etc/hosts
这将检查(中的每个 IPv4/IPv6 环回分配/^127\.|^::1[[:space:]]/
匹配以文字“127.”开头的每一行(对于 IPv4 环回,或以任意数量的零和冒号开头::1
,以及一个空格(对于 IPv6 环回))作为旧主机名,并将其转换为新主机名(通过循环遍历每个项目并仅替换那些完全匹配的项目 - 注意,受影响的行中的所有空格将被单个空格字符替换)。然后打印所有行(无论是否修改)。
因为awk
没有像 这样的内联编辑模式sed -i
,所以必须将其保存到新文件(/etc/hosts.new
)。然后我们将diff
新文件与旧文件进行比较。如果它们相同,则删除新文件。如果它们不同,则备份旧文件(我为备份选择了基于日期的文件名,例如/etc/hosts.20200212
)。成功备份旧版本后( 确保&&
只有前一个命令报告成功时才会运行下一个命令),我们可以将新版本移动到其正确位置。
答案2
ip a list lo
实际上这是我的 debian 10 buster命令的输出:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
如您所见,有一个 /8 掩码,因此(127.0.1.1 和 127.0.0.1)都将发送到此接口,因此无论您写 127.0.0.1 还是 127.0.1.1,在任何 Linux 发行版上都是相同的。据我所知。
根据这个脚本,无需检查我是否会离开ipv4_localhost_re="127\.0\.1\.1"