127.0.1.1ってなに？ あるいは、Ubuntu含むDebian系でホスト名をちゃんと変更するスクリプトのはなし

## ホスト名を変更するbashスクリプト

「127.0.0.1は、localhostでしょ？ んん？127.0.1.1ってなによ。」

この話、ラズパイからのスタートですが、Ubuntu含むDebian系でも通用する、かもしれません。

ラズパイの初期設定、今までにも何百台かやってきましたが、一台あたり２つのファイルを編集して、すべてユニークなホスト名に変えていました。自分でやったり、子供たちにやってもらったり。

今回、またラズパイをたくさん設定する機会があり、かんたんにホスト名を変更できるような工夫をしてみました。いろいろ調べて、自分でスクリプトを書いたのですが、この記事をまとめている時に、更に深い状況を知りました。結果的に自作スクリプト、あんまり出番ない。。

せっかく書いたので、change_host_nameというのを置いておきます。一番最後にあります。参考にはなると思います。（[ジャンプ](#change_host_name)）

**結論：公式コマンドraspi-configだけを使っている分には問題なし。ただ、なにかの拍子にエラーが頻発する可能性あり。そのうち、本家にプルリク入れます。**


## 従来のホスト名変更法、4種と、たまに不具合
1. CUIで、```sudo hostnamectl set-hostname host-name-xxxx```で変更。(Debianのツール) 
1. GUIで、「メニュー／設定／Raspberry Piの設定」を開き、「システム／ホスト名」を変更。
1. CUI / GUIで、```sudo raspi-config``` 1. System Options -> S4 Hostname で変更。
1. CUIで、```sudo raspi-config nonint do_hostname host-name-xxxx```で変更。
1. CUIで、/etc/hostname、/etc/hostsを編集して、変更。


1は、Debianのツール、hostnamectlですが、これを使うと、/etc/hostnameだけが書き換わり、/etc/hostsがそのままになってしまい、sudoコマンドを使った時に、毎回、エラーメッセージが出るのです。最近のUbuntuでは、このエラーが出なくなっているかも。


```
sudo: ホスト host-name-xxxx の名前解決ができません: 名前またはサービスが不明です
```

2から4は見え方が違うだけで、ラズパイ独自のraspi-configですね。
このツールもある意味、不具合があって、何らかの形で（hostnamectl使ったり、個別に編集したり）/etc/hostsでの設定が/etc/hostnameとずれているとき、修正してくれません。そうなると、同上のエラー。自作スクリプトを書いたときにもチェックしたのですが、「/etc/hostsは設定されないな」と思ってしまい、通過。

ということで、結局、いつも、5、ふたつのファイルを書き換えていました。
マシンが1台、2台だったら、問題ない。まぁ、sudo（管理者権限）で、ちょこちょこっと書き換えればよいだけなので。


ちなみに、ubuntu 20.04では、127.0.1.1の行のパターンが違う。
127.0.1.1       host-name-xxxx.localdomain     host-name-xxxx


## そもそも、/etc/hostsの127.0.1.1って、何なの？？

公式の方法でも、不具合があるって、どういうこと？？
/etc/hostsに書かれている、127.0.1.1の行は、どういう意味？？
世界中で、20年近く、多くのDebian系ユーザーを悩ませてきました。（ちょっぴり大げさ、でも事実）

私も、6,7年前に「いろいろ調べたけど、よくわからんし、2つのファイルを書き換えれば良いのはわかった。」ってなって、そのまま放置していました。

/etc/hostname

```/etc/hostname
host-name-xxxx
```

/etc/hosts

```/etc/hosts
127.0.0.1	localhost
::1		localhost ip6-localhost ip6-loopback
ff02::1		ip6-allnodes
ff02::2		ip6-allrouters

127.0.1.1	host-name-xxxx
```


## 127.0.1.1の意味、できた経緯がわかりました

ググって、ググって、わかりました。言ってみれば、色んな人を悩ませるというところまで含めて、仕様バグ状態、かな。

固定IPアドレスが存在する前提で動くシステム／ツール／アプリが不具合を起こすので、回避法として、**とりあえず**、127.0.1.1を割り当てることが決定、実装されました。インストーラーの中でnetcfgがやってます。

###**Debian公式の説明**
Chapter 5. Network setup
5.1.1. The hostname resolution
https://www.debian.org/doc/manuals/debian-reference/ch05.en.html#_the_hostname_resolution

>The IP address 127.0.1.1 in the second line of this example may not be found on some other Unix-like systems. The Debian Installer creates this entry for a system without a permanent IP address as a workaround for some software (e.g., GNOME) as documented in the bug #719621.



###**「仕様バグ」誕生の瞬間**

####回避策としての127.0.1.1の実装提案
Subject: Re: Proposed new scheme for resolving the system hostname
Date: Fri, 24 Jun 2005 12:34:52 +0200
https://lists.debian.org/debian-boot/2005/06/msg00938.html

####127.0.1.1実装の具体案
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=316099#5
Subject: Please give system hostname IP address 127.0.1.1
Date: Tue, 28 Jun 2005 14:38:04 +0200

####netcfg 1.13での実装、決定。
提案から各メンバーの意見まで含まれています。
Date: Fri, 19 Aug 2005 13:17:41 -0700
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=316099#16

要するに、暫定措置が永らく生き残っているということです。

## 固定IPで運用する人への注意

/etc/hostsの127.0.1.1行を単純にコメントアウトしてはいけません。
固定ipアドレスに書き換えましょう。いろいろと不具合が発生するらしいです。
例えば、```df -H``` で、ディスクの空き容量がゼロ、とか。

### ディスクの空き容量がゼロ！事件
実害はないみたいだけど、困る。
https://raspberrypi.stackexchange.com/questions/32969/purpose-of-127-0-1-1raspberrypi-entry-in-file-etc-hosts

## change_host_name

おまたせしました、肝心のスクリプトです。


```
#!/bin/bash
echo 'Going to set the new name ' \"$1\" ' to /etc/hostname and /etc/hosts.'
read -p  "Are you sure? (Y/n) " -n 1
#[[ $REPLY = [Nn] ]] && exit 1
[[ $REPLY = [Nn] ]] && echo && echo 'bye...' && exit 1

echo
echo '---- Current settings ----------'
echo '/etc/hostname:'
cat /etc/hostname
echo '--------'
echo '/etc/hosts:'
cat /etc/hosts
echo '--------------------------------'
echo
echo -n  '** change host name to '
echo $1 | sudo tee /etc/hostname
sudo sed -i -e 's/127.0.1.1.*/127.0.1.1\t'$1'/' /etc/hosts
echo
echo '---- New settings --------------'
echo '/etc/hostname:'
cat /etc/hostname
echo '--------'
echo '/etc/hosts:'
cat /etc/hosts
echo '--------------------------------'
```

### 使い方
実行権限を与えて、使ってください。Nまたは以外のキー入力で実行、エンターだけでも実行。

```
chmod u+x change_host_name

使うときは、
./change_host_name host-name-xxxx
sudo reboot
```
例の「名前またはサービスが不明です」が出ますが、再起動すればなくなります。

### スクリプトの解説
だらだらと書かれていますが、肝心なのは2行だけ。

```
# /etc/hostnameを上書き
echo $1 | sudo tee /etc/hostname
```

```
# /etc/hostsから、127.0.1.1の行を検索して、書き換え
# 元のホスト名設定にかかわらず、書き換えているのがポイント。
sudo sed -i -e 's/127.0.1.1.*/127.0.1.1\t'$1'/' /etc/hosts
```

/etc/hostname修正については、ホントは、ちゃんとしたコマンドもあった。。これが中途半端。

    sudo hostnamectl set-hostname host-name-xxxx



## おまけ
hostnamectlの出力。

```
hostnamectl
   Static hostname: host-name-xxx
Transient hostname: transient-host-name-xxx
         Icon name: computer
        Machine ID: 093a2653df5d4a9abb13d6c578a3fea0
           Boot ID: 3665f1d1e7fa44359272638574232b31
  Operating System: Raspbian GNU/Linux 10 (buster)
            Kernel: Linux 5.10.7-v7l+
      Architecture: arm
```

コマンド```sudo hostnamectl --transient set-hostname host-name-xxx```でホスト名を変更すると、再起動するまでの間、Transient hostnameが存在します。



## さらに、おまけ

おおおおー、記事を書き終わったと思ったら、発見。Stack overflowでまともなスクリプトを書いている人がいた。たぶん、誰も読んでないけど。同じことやってます。これを先に見つけてたら、このスクリプトの紹介をしていたでしょう。
https://stackoverflow.com/a/59241184/911156

なるほど、さらにググると、これはラズパイ公式ツール、要するにraspi-configの抜粋だった。

raspi-configのコード
https://github.com/RPi-Distro/raspi-config/blob/74885481d8f311ab3875b6601153132552b41d67/raspi-config#L592

```
sed -i "s/127.0.1.1.*$CURRENT_HOSTNAME/127.0.1.1\t$NEW_HOSTNAME/g" /etc/hosts
```
/etc/hostsが現在のホスト名（/etc/hostnameでの設定）とずれていたら、何もしない。ここが問題。2回目以降、うまく行かない。以下の強制上書き方式が良いと思う。

```
sed -i "s/127.0.1.1.*/127.0.1.1\t$NEW_HOSTNAME/g" /etc/hosts
```



##参考リンク

Raspberry Pi Forumでも話題になってた。
https://www.raspberrypi.org/forums/viewtopic.php?t=115257

経緯について詳しい。
https://serverfault.com/questions/363095/why-does-my-hostname-appear-with-the-address-127-0-1-1-rather-than-127-0-0-1-in