This is to differentiate between the host's name and 'localhost.localdomain' since they could be confused on hosts without known fixed IP addresses.
Localhost is 127.0.0.1 but there are 16.7 million IPs in the reserved loopback IPv4 space (all of 127.*.*.*
, 127.0.0.1 through 127.255.255.255, as denoted by the CIDR 127.0.0.0/8); all IPs in that space resolve identically.
Your linked Debian bug 316099 adds this changelog item for netcfg 1.1.3 (2005):
If there is no permanent IP address with which the system hostname (i.e., that which is returned by the hostname
command) can be associated in /etc/hosts then associate it with address 127.0.1.1 rather than 127.0.0.1. Associating the system hostname with the latter had the unwanted effect of making 'localhost.localdomain' the canonical hostname associated with the system hostname. That is, hostname --fqdn
returned 'localhost.localdomain'.
The script you found is modifying the system name as stored in /etc/hosts
, whose keying IP differs based on Linux distribution as we just established. It's a bit messy of an implementation, but it should work, swapping each /etc/hosts entry for IPv6 and the distro's favored localhost IPv4 to the new host name and saving the results on top of the original.
Note that there is no backup and if there are other mappings for that IP, they're likely overwritten. It assumes the system name is the last column of those lines, which may or may not be true. For example, 127.0.1.1 home my-box-oldname localhost
would become 127.0.1.1 home my-box-oldname my-box-newname
and you'd lose localhost
.
I've had bad experiences with /etc/hosts
having multiple definitions on the same line, so on one of my systems, that could have resulted (before this bug fix) in:
127.0.0.1 localhost
127.0.0.1 my-box-oldname
127.0.0.1 alternate-name1
127.0.0.1 alternate-name2
turning into the unhelpful
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
I cannot answer whether other distros have adopted this move, but seeking /etc/debian_version
does seem a bit mismatched on a questionable assumption. I'd personally prefer explicitly searching /etc/hosts
for the old host name.
Consider this drop-in replacement for the code snippet you provided (which also addresses my two previous complaints):
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
This checks every IPv4/IPv6 loopback assignment in /etc/hosts
(/^127\.|^::1[[:space:]]/
matches every line starting with a literal "127." for IPv4 loopback or else any number of zeros and colons before ::1
and a space for IPv6 loopback) for the old host name and converts just it to the new one (by looping through each item and replacing only those that match in their entirety—note, affected lines will have all white space replaced by a single space character). All lines, modified or not, are then printed.
Because awk
doesn't have an in-line edit mode like sed -i
, this has to save it to a new file (/etc/hosts.new
). We then diff
the new file with the old one. If they are the same, remove the new file. If they differ, back up the old one (I've chosen a date-based filename for the backup, e.g. /etc/hosts.20200212
). With the old version successfully backed up (the &&
ensures the next command is only run if the former command reports success), we can move the new version to its proper place.