知に至る病

お勉強したことを忘れないように書き留めています。

Cygwin 2.4.1 以降でコマンド置換が働かないのは MacType が原因でした

Cygwin 64bit 版を 2.4.1 にアップデートしたら,特定の条件下でコマンド置換がうまく働かなくなりました。 半月ほど悩まされましたが,ついに MacType が原因であることがわかり解決しました。 同じ症状で悩む人がいるかもしれませんのでメモを残しておきます。

この記事を投稿した時点で Cygwin の最新バージョンは 2.5.0 になっていますが,同じ問題が発生することを確認済みです。

なお,この問題は 64bit 版だけで見られるもののようです。 32bit 版では確認できませんでした。

症状

特定の条件下でコマンド置換がうまく働かなくなりました。 たとえば,ファイルのハッシュ値を変数に代入し,すぐに出力するコマンドを実行してみます。 コマンド置換でエラーが発生しているのか,変数に空文字列が代入されてしまうため,何も表示されません。

$ for f in *;
> do
> HASH=`md5sum $f | cut -d " " -f 1`
> echo $HASH
> done



...

変数に代入せず直接 echo すればちゃんと出力されます。

$ for f in *
> do
> echo `md5sum $f | cut -d " " -f 1`
> done
b1946ac92492d2347c6235b4d2611184
591785b794601e212b260e25925636fd
c59548c3c576228486a1f0037eb16a1b
...

いろいろパターンを変えて試した結果,コマンド置換にパイプが含まれている場合のみ,直後に別のコマンドを連結して実行すると構文解析でコケる(らしい)ことがわかりました。 for 文は do ~ done ブロックの内容を ; で連結した形で実行されるのでエラーになっていると思われます。 ; だけでなく,||&& といった他の連結記号でも同じ症状が出ます。

原因と解決策

どうやら原因は MacType のようです。 MSYS2 の Discussion にそれらしい情報を見つけて,試してみたら当たりでした。 MacType を停止した状態では症状が再現されません。

MacTypeCygwin と競合する可能性があるプログラムとして FAQ のリストにもちゃんと載っていました。 このリストは BLODA(Big List Of Dodgy Apps)と呼ばれているそうです。 セキュリティソフトなど常駐型のプログラムが多く名を連ねています。

MacType が原因とわかりましたので,解決策としては CygwinMacType の処理対象から除外してやればよいことになります。 MacType のプロセスマネージャーで bash.exe を選択し,コンテキストメニューから「このプロセスを除外」にチェックすれば OK です。 もちろん,*.ini ファイルを直接編集してもよいと思います。

2016-04-22 追記

bash.exe を除外するだけでは不十分でした。 シェルスクリプト/bin/sh で実行されることが多いため,このままではシェルスクリプト内でコマンド置換を使用している場合に問題が起こる可能性があります。

たとえば,git rebase --interactive を実行すると,以下のようなエラーが発生しました。

$ git rebase -i e563d21
/usr/libexec/git-core/git-rebase--interactive: 行 125: + : 構文エラー: オペランドが予期されます (エラーのあるトークンは "+ ")

該当箇所では rebase の進捗を表示するためにコマンド置換を利用してカウントしています。 コマンド置換で失敗して二項演算子 +オペランドが空になっているので,シンタックスエラーが発生しているようです。

new_count=$(git stripspace --strip-comments <"$done" | wc -l)
echo $new_count >"$msgnum"
total=$(($new_count + $(git stripspace --strip-comments <"$todo" | wc -l)))

MacType の除外リストに sh.exe を追加してやるとこのエラーは解消されました。 しばらくこのままで様子を見ようと思いますが,git 関連でエラーが出るのは正直怖いので,MacType の使用自体を中止することも考えています。

なお,同様の問題が Git for WindowsGitHub Issue にも上がっていました。