コンソールタイプによってプロセスの環境変数LANGが変化する
※過去にまとめたwikiからの移行記事
Linuxの環境によってはコンソールタイプの違いにより、プロセスの環境変数LANGが変化することがある。
まずは、前提知識からおさらいしておく。
前提知識
標準入力に接続されているデバイス
Linuxではマシンにどのように接続したかによって端末デバイスが変わる。
例えば、マシンと物理的に接続されたキーボード・モニタから、あるいはコンソールでログインした場合の接続デバイスは/dev/ttyX(Xは数字)となる。
また、遠隔マシンにsshやtelnetで接続した場合の接続デバイスは/dev/pts/X(Xは数字)となる。
自分がログインしている端末を確認するためには以下のコマンドを実行してみる。
> tty /dev/pts/0
コンソールタイプ
consoletypeコマンドを実行した時に表示される接続デバイスの種類のこと。
以下のように表示される。
- コンソールから実行
> consoletype vt
- SSHで実行
> consoletype pty
まとめると以下の通り。
接続方法 | 物理(もしくはコンソール)接続 | SSH接続 |
---|---|---|
端末デバイス名 | /dev/ttyX | /dev/pts/X |
コンソールタイプ | vt | pts |
本題
前提知識の話も終わったところで本題に入る。
先ほどのコンソールタイプの違いによっては、プロセスの環境変数LANGが変化してしまうのだ。
この問題は実際に見た方が早いので実験してみた。
なお、環境はCentOS6.10、ロケールはja_JP.UTF-8を設定している。
> cat /etc/sysconfig/i18n LANG="ja_JP.UTF-8"
まずは、以下のように適当なプロセス(ここではrpcbind)の環境変数を見てみる。
> strings /proc/1521/environ (略) LANG=ja_JP.UTF-8 (略)
上記のように、rpcbindのLANGはja_JP.UTF-8となっている。
では、ここでコンソール端末からrpcbindサービスの再起動を行い、再度プロセスの環境変数を確認してみる。
> service rpcbind restart rpcbind を停止中: [ OK ] rpcbind を起動中: [ OK ] > strings /proc/1230/environ (略) LANG=en_US.UTF-8 (略)
rpcbindのLANGがen_US.UTF-8に変化してしまっている。
では、今度はSSH端末からサービスの再起動を行ってみる。
> service rpcbind restart rpcbind を停止中: [ OK ] rpcbind を起動中: [ OK ] > strings /proc/1560/environ (略) LANG=ja_JP.UTF-8 (略)
今度はja_JP.UTF-8に変化した。
最後にOS再起動を行った後のLANGを確認する。
> reboot (再起動後) > strings /proc/1226/environ (略) LANG=en_US.UTF-8 (略)
再起動後はen_US.UTF-8となった。
実験結果をまとめると以下の通り。
サービス起動方法 | コンソール | SSH | OS再起動 |
---|---|---|---|
LANG | en_US.UTF-8 | ja_JP.UTF-8 | en_US.UTF-8 |
LANGが変化する理由
CentOS(RHEL)6系ではServiceコマンドで再起動、あるいはOS再起動を行うと、
/etc/profile.d/lang.shが呼ばれることで環境変数の設定が行われる。
このlang.shを見てみると、以下のようになっている。(長いので一部を抜粋)
if [ -n "$LANG" ]; then case $LANG in *.utf8*|*.UTF-8*) if [ "$TERM" = "linux" ]; then if [ "$consoletype" = "vt" ]; then case $LANG in ja*) LANG=en_US.UTF-8 ;; ko*) LANG=en_US.UTF-8 ;; si*) LANG=en_US.UTF-8 ;; zh*) LANG=en_US.UTF-8 ;; ar*) LANG=en_US.UTF-8 ;; fa*) LANG=en_US.UTF-8 ;; he*) LANG=en_US.UTF-8 ;; en_IN*) ;; *_IN*) LANG=en_US.UTF-8 ;; esac fi fi
lang.shではTERMが"linux"*1、consoletypeが“vt”の場合、LANGをen_US.UTF-8に設定する。
要するにコンソールでログインしている状態では、LANGがen_US.UTF-8となってしまうのだ。
そのため、いくら/etc/sysconfig/i18nでロケールをja_JP.UTF-8に設定していても、
OS再起動時あるいはコンソールでのプロセス再起動時に、LANGがen_US.UTF-8となる。
SSH接続している場合には、lang.shの条件分岐に引っかからず(consoletypeがptsであるため)、 /etc/sysconfig/i18nで設定したロケール通りにja_JP.UTF-8となる。
なお、以上の問題はCUI環境で発生する問題であり、GUI環境では発生しない。
(GUI環境では$TERMがlinuxではなく、xtermとなるため)
*1:http://archive.linux.or.jp/JF/JFdocs/Text-Terminal-HOWTO-15.html によると、コンソール接続時における設定値。