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 を停止した状態では症状が再現されません。
MacType は Cygwin と競合する可能性があるプログラムとして FAQ のリストにもちゃんと載っていました。 このリストは BLODA(Big List Of Dodgy Apps)と呼ばれているそうです。 セキュリティソフトなど常駐型のプログラムが多く名を連ねています。
MacType が原因とわかりましたので,解決策としては Cygwin を MacType の処理対象から除外してやればよいことになります。
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 の使用自体を中止することも考えています。