あらまし
お仕事の成果物チェックを find . -type f | sort
とdiff -q
で比較して足りないファイルがないかチェックするようにした。
find . -type f | sort > files.txt
diff -q files-expected.txt files.txt
手元の環境で問題がなかったのでいざJenkinsで動かしたところ、
奇妙なことにまったく同じディストリビューション、コマンド、ファイルを入力に使ったにも関わらずエラーとなった。
調査
問題を最小化してみた。
手元
$ find . -type f | sort
A.txt
B.txt
a.txt
b.txt
Jenkins
$ find . -type f | sort
a.txt
A.txt
b.txt
B.txt
大文字と小文字の扱いが変わっているようだ。
原因
手元とJenkins環境を徹底的に調べたところ、LANGの値が異なった。
手元
$ echo $LANG
ja_JP.UTF-8
Jenkins
$ echo $LANG
en_US.UTF-8
検証
LANG=C
$ echo -e "a\nb\nA\nB"| LANG=C sort
A
B
a
b
LANG=ja_JP.UTF-8
$ echo -e "a\nb\nA\nB"| LANG=ja_JP.UTF-8 sort
A
B
a
b
LANG=en_US.UTF-8
$ echo -e "a\nb\nA\nB"| LANG=en_US.UTF-8 sort
a
A
b
B
やはりLANG
が影響している。
sort
はLANG
を見ているのか
sort
のman pageにはLANG
を見るとは一言も書いていない。
ではどこから差が来るのか
http://linux.die.net/man/3/strcoll
http://linux.die.net/man/3/setlocale
とてもわかりにくいが、整理すると以下のようになる。
-
strcoll()
という文字比較関数が標準Cライブラリにある - この関数は、
LC_COLLATE
というロケールカテゴリによって挙動が変わる - ロケールを参照する場合、
LC_COLLATE
のカテゴリなら、LC_ALL
,LC_COLLATE
,LANG
の順に値を見ていく
どうやらロケールの値は環境変数で変えられるようで、
今回はLANG
の値が異なったことが原因で挙動が違ったようだ。
ロケールの値はlocale
で参照できる(コメント欄参照 THX @magicant )
最後に
メジャーなコマンドラインツールが異なる挙動を示したらとりあえずlocale
を。