2022年1月アーカイブ

Linux memo 2022/01/16 locale編

● ネタ
Q. 2台あるLinuxマシンでのdateコマンドの実行結果のformatが異なる
A. 結局わからんかった

● LC_TIME
dateコマンド(coreutils)は出力フォーマットを指定することができるが、指定しなかった場合、環境変数LC_TIMEにあるlocaleに従ったフォーマットになる。たいていは "ja_JP.UTF-8" などの文字列が入っている。dateコマンドはnl_langinfo()関数を使いlocaleからフォーマット文字列を持ってきて使う。取れなかった場合"%a %b %e %H:%M:%S %Z %Y"を指定したものとして扱われる。(CentOSなどでは/etc/locale.confも使われる?)

● ssh時の環境変数
sshコマンド(OpenSSH)でリモートにログインするとき、通常はlocale関連の環境変数をローカルからリモートに引き継ぐようになっている。これは /etc/ssh/ssh_config にある「SendEnv LANG LC_*」の設定によるもの。これにより「どこからログインしたか」でdateの出力フォーマットが変わることになる。「こう設定しているはず」と思い込みをせずにそのshellごとに環境変数を確認しよう。

● locale
localeはi18nからlocaledefで作られるDBを引っ張ってくることで個別の情報を引っ張ってくる。Ubuntu-20.04の場合、/usr/share/i18n/locales/en_CA にある「date_fmt "%a %d %b %Y %r %Z"」からDBが作られている模様。DBは/usr/lib/locale以下に配置されている。

● TZ
dateコマンドはデフォルトではローカルタイムを表示するが、ローカルタイムとは環境変数TZもしくは/etc/localtimeで指定されたTZデータベースのものとなる。日本だとGMT+9すればよいからあまり意識しないが、サマータイム補正しないといけない国も多いため、サマータイム情報も入ったTZデータベースが必要となる。ちなみに日本でも1948年から1951年にサマータイムが導入されていたため「存在しないローカル時刻」でたまにハマる人がいる。

● 敗因
localeがミスマッチなしに機能している間はいいんだけど、aliasになっていたり指定したlocaleが見つからなかったり環境変数がなかった場合に、C.UTF-8を見に行くのか/etc/locale.confを使うのかnl_langinfo()ライブラリに組み込まれたデフォルトが使われるのかdateプログラムに組み込まれたデフォルトを使うのか、このへんがわからんかった。

● 少しだけ気になったところ
localeのLC_MEASUREMENTには、1(Metric)か2(US customary measurements)を指定できるらしいが、en_GBの場合は1になっており、「イギリスってメートル法に変わったんだったっけ?」とかムダに調べてしまった。移行しようとしているが慣習的にまだまだ浸透していない状態らしい(2021年の情報)。英語でメートル法で数字区切りが,小数点が.、な地域を選ぶとすると、オーストラリア・ニュージーランド・アイルランド・カナダ、あたりとなる。日付フォーマットだけは日本と同じ形式なとこが少なすぎてどうにもならん。

● 所感
Linuxをインストールするときは言語はもう英語にしているけど、localeだけは気になり(特に日付)、en_USではなくen_CAに設定していたんだけど、en_CAのlocaleなんてわざわざインストールしていない環境も多く、上記のようにハマることになってしまった。カスタマイズできる機能を提供してしまったがために逆にハマることになってしまっている気がする。

このアーカイブについて

このページには、2022年1月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2021年9月です。

次のアーカイブは2022年2月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

月別 アーカイブ

ウェブページ

Powered by Movable Type 7.9.0