0

My question is related to this question:

In some bash script I found this snippet here:

...
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
...

I'm wondering whether this method for editing the hostname is still correct for all other stems of Linux distributions and whether and how those other distributions handled the problem which was originally reported as Debian Bug in 2005 and which led to the introduction of the 127.0.1.1 workaround which seems to be still being used in Debian, Ubuntu and so on until today but not in Fedora, SuSE, and many others (If my research is correct).

To summarize: Do you know a Linux distribution out there which is not based on Debian or has no longer a /etc/debian_version file but has still adopted this 127.0.1.1 solution?

pefu
  • 629
  • 6
  • 20

2 Answers2

2

Actually this is the ouput from the comman ip a list lo my 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

As you can see there's a /8 mask so both (127.0.1.1 and 127.0.0.1) will be sent to this interface so doesn't matter if you write 127.0.0.1 or 127.0.1.1, will be the same on any linux distribution. As far as I know.

On that script there's no need to check that I'll just leave ipv4_localhost_re="127\.0\.1\.1"

VictorMJ
  • 108
  • 5
  • I assume: The hostname of your Debian 10 (butster) installation is on a separate line containing the IPv4 address 127.0.1.1 and localhost is on another line. Right? – pefu Feb 11 '20 at 13:21
1

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.

Adam Katz
  • 869
  • 8
  • 16
  • 1
    Thank you very much for your elaborate description. But this does not answer my question whether looking for the /etc/debian_version file is still sufficient today. Since this workaround has been introduced to Debian nearly 15 years ago and is still sucessful I wondered whether other non Debian based distributions might have adopted this approach too. – pefu Feb 12 '20 at 10:46
  • While I can't answer that, I can provide code that works regardless of the distribution. See the latest version. – Adam Katz Feb 12 '20 at 16:51