ansibleで文字化け

ansible playbook を書く時は、各タスクの name に日本語で内容を記載するようにしていますが、突然この文字列が文字化けするようになりました。「ansible 文字化け」でもヒットしなかったので、以下の通りメモっておきます。

事象

name タグに記載した日本語文字列が、ことごとく ‘?’ になっています。ただこれを除けば、ansible-playbook 自体は正しく動いているようです。

vagrant@onumap:~/onumap-deploy$ ansible-playbook onumap.yml
(中略)
TASK [base : ?????????] ********************************************************
ok: [localhost]
...

(質問サイトに出すために)いろいろと再現条件を試していたら、ansible コマンド単体でも再現することを確認しました。

vagrant@onumap:~$ export MOJIBAKE=文字化け
vagrant@onumap:~$ env | grep MOJIBAKE
MOJIBAKE=文字化け
vagrant@onumap:~$ ansible -m setup localhost | grep MOJIBAKE
            "MOJIBAKE": "????",

環境

vagrant@onumap:~$ cat /etc/system-release
CentOS Linux release 7.8.2003 (Core)
vagrant@onumap:~$ rpm -qa|grep ansible
ansible-2.9.9-1.el7.noarch

いままで動いていたのになぁ。従来と違うところと言えば、Vagrant 経由で建てた VM が CentOS 7.8 になったところくらい?

(直接の)原因

今回の原因は、まさかの環境変数でした。ちゃんと日本語(LANG=ja_JP.utf8)にしているのに‥。

vagrant@onumap:~$ export LANG=C
vagrant@onumap:~$ ansible -m setup localhost | grep MOJIBAK
            "MOJIBAKE": "????",
vagrant@onumap:~$ unset LANG
vagrant@onumap:~$ env | grep LANG
vagrant@onumap:~$ ansible -m setup localhost | grep MOJIBAK
            "MOJIBAKE": "????",

これでも直らなかったんですが、

vagrant@onumap:~$ export LANG=en_US.UTF-8
vagrant@onumap:~$ ansible -m setup localhost | grep MOJIBAK
            "MOJIBAKE": "文字化け",

なんと、これで直るというね‥?

ただこれだと、本来の LANG の重要な意図であるメッセージ出力の切り替えはどうなるんだろう?

vagrant@onumap:~$ LANG=ja_JP.utf8 ls abc
ls: cannot access abc: No such file or directory

案の定、メッセージが日本語にならない。

ロケールの設定

CentOS7 では、ロケールの設定は localectl コマンドでやるようです。localectl list-locales で設定可能なロケール一覧が表示されます。

vagrant@onumap:~$ localectl list-locales | grep ^ja

あれ?何も出てこない。一覧表示すると、en で始まるものだけしかない。

ロケールが足りない場合は glibc-common を再インストールするとよいそうです。Vagrant box にする時に、イメージサイズを小さくするためにロケールデータがカットされてしまっているのかもしれません。

今回の手順は、そもそもアプリのデプロイを ansible で自動化しようとしている最中の出来事なので、glibc-common の再インストールも ansbile (yum モジュール)でやるべきです。ところが、今度は yum モジュールが reinstall をサポートしていないときた。

調べてみると、GitHub で Issue(RFE: state: reinstalled for yum module #35324) が立ってました。まだ実装されていないようなので、command / shell モジュールでやるしかないみたいです。

ここまでやったら、やっと元の設定である

LANG=ja_JP.utf8

に戻しても、ちゃんと日本語を表示してくれるようになりました。

それでも ansible ではやっぱりダメ

(2020/05/27 追記)

この手順を駆使しても、ansible ではうまくいきませんでした。おそらくですが、ansible で local_connection を使っていて、同じ(bash 上の)セッションの中で playbook が動くので、そのセッションが終わるまではロケール環境の変更が反映されないからだと想像しています。ansible には reset_connection という機能があるのですが、local だと

ansible reset is not implemented for this connection

と言われてしまいました。しかたがないので、README.md に「vagrant 環境でやる場合は最初に一発

$ sudo yum -y reinstall glibc-common

を流してからやってください。」という但し書きを入れることでお茶を濁してしまいました。残念。

参照

タイトルとURLをコピーしました