ホスト名を変更するbashスクリプト
「127.0.0.1は、localhostでしょ? んん?127.0.1.1ってなによ。」
この話、ラズパイからのスタートですが、Ubuntu含むDebian系でも通用する、かもしれません。
ラズパイの初期設定、今までにも何百台かやってきましたが、一台あたり2つのファイルを編集して、すべてユニークなホスト名に変えていました。自分でやったり、子供たちにやってもらったり。
今回、またラズパイをたくさん設定する機会があり、かんたんにホスト名を変更できるような工夫をしてみました。いろいろ調べて、自分でスクリプトを書いたのですが、この記事をまとめている時に、更に深い状況を知りました。結果的に自作スクリプト、あんまり出番ない。。
せっかく書いたので、change_host_nameというのを置いておきます。一番最後にあります。参考にはなると思います。(ジャンプ)
結論:公式コマンドraspi-configだけを使っている分には問題なし。ただ、なにかの拍子にエラーが頻発する可能性あり。そのうち、本家にプルリク入れます。
従来のホスト名変更法、4種と、たまに不具合
- CUIで、
sudo hostnamectl set-hostname host-name-xxxx
で変更。(Debianのツール) - GUIで、「メニュー/設定/Raspberry Piの設定」を開き、「システム/ホスト名」を変更。
- CUI / GUIで、
sudo raspi-config
1. System Options -> S4 Hostname で変更。 - CUIで、
sudo raspi-config nonint do_hostname host-name-xxxx
で変更。 - 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
host-name-xxxx
/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