glibcを更新しても大丈夫な「正しい」タイムゾーンの設定方法 (2/3追記あり)

RHEL, CentOS, Amazon Linux (6以前)

/etc/localtime を /usr/share/zoneinfo 以下から上書きしたりシンボリックリンク張ったりという手法が横行していますが、 /etc/localtime は glibc パッケージに含まれるためパッケージを更新すると上書きされてESTとかに戻ってしまうわけです。

当然ながら、ディストリビューションとして正しい設定方法が用意されているので、こちらを使います。

  1. /etc/sysconfig/clock にタイムゾーンを書きます。*1
    sudo sed -i -e "s/^ZONE/#ZONE/g" -e "1i ZONE=\"Asia/Tokyo\"" /etc/sysconfig/clock
  2. tzdata-update を実行します。
    sudo /usr/sbin/tzdata-update

これだけです。glibcのパッケージをアップデートした時にも、glibc-commonのトリガスクリプトとしてtzdata-updateが自動で呼ばれます。sysconfigで設定してコマンドで現状に反映させるという普通のRHELの世界観そのままですね。

ちなみに、よりRHELの世界観に沿うために、CUIのグラフィカルインターフェースとして system-config-date が用意されていますが、忘れて良さそうな気がします。

(補足) EL7以降というかsystemd系ディストリビューションはtimedatectl(man)使うとのこと。

Ubuntu, Debian GNU/Linux

Debian系というぐらいでdebconf ベースですが、 /etc/timezone を参照してdebconfのデータベースに反映してくれるようになっています。Debianは使っていないので未確認ですが、同じで良いとのこと。

  1. /etc/timezone にタイムゾーンをベタで書きます。
    echo "Asia/Tokyo" | sudo tee /etc/timezone
  2. dpkg-reconfigureでdebconfの設定処理を走らせます。
    dpkg-reconfigure --frontend noninteractive tzdata

CUIでカーソル選択とかしたくない人がほとんどだと思うので、 noninteractive 積極的に使っていきましょう。

ディストリの世界観

今回の「glibc更新するとタイムゾーンがリセットされる!?」とかそうですが、普通に作業して明らかに面倒とか不便とか問題があったら、そのまま回避策を採るのでは無く、まずその設定方法がディストリビューションの世界観に沿っているかを疑ったほうが「急がば回れ」になります。

というか、こういうの探すときに、「ディストリビューションが提供しようとしている世界観」を意識するかどうかで探し方全然変わるので、誰かまとめて欲しい。

超ざっくりこれ:

  • EL系: 設定は/etc/sysconfig 以下に書く。反映方法は割と適当。
  • Debian系: 設定は debconf のデータベースに登録し、dpkg-reconfigureで反映
  • systemd系: なんちゃらctl
  • Gentoo: emergeがなんとかしてくれる

追記: 2015-01-31 01:21

/etc/sysconfig/clock の既存設定を残すよう、tee -a に変更しました。
「正しい」とか煽りながら非互換だしていてすみませんorz

さらに追記 2015-02-03 17:12

tzdata-update は、/bin/sh等に依存しないようにC言語で書かれた小さなプログラムなのですが、最初のZONE指定が有効になるようです*2。安易にtee -aで追記にしたら反映されないというご指摘を頂きました。

sysconfig 以下のファイルは通常はシェルスクリプトとして解釈されるという思い込みがあったのですが、記事修正するときに検証を怠った結果がこれです。
ざっと確認した範囲では見つけられなかったのですが、自前で /etc/sysconfig/clock を呼んでいるシェルスクリプトがあると危険なので、記事無いの置換コマンドは、単純な追記で無く既存のZONE行を潰してから先頭に追記するようにしました。

というわけで、/etc/sysconfig の一般的な文法(これも「世界観」の一部)から外れることもあるので、盲信せずきちんと検証しましょうという良い教訓でした。記事書いて良かった……。

*1:tzdata-update は最初の記述が有効になりますが、シェルスクリプトとして他のソフトウェアから読まれる可能性があるため、他のZONE行は消して置いた方が良いと思います。

*2:たぶんこの辺。見つかったら即breakしてる。 https://www.sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=fedora/tzdata-update.c;h=33bb8c67e379c88dc4af0fcbf5dc33c55973302f;hb=9da0dd7c81b1cedd383e0eba09c9452d2874f862