🔖

passコマンドが最近上手く動かなくなった時の対処法[tree v2.0.0関連]

2022/02/07に公開

これは自分のブログ記事の転載です。


passコマンドは内部でtreeコマンドを使用しています。このところ、treeコマンドの使用変更によってpassコマンドが上手く動かなくなったのでその原因と対処法について書き残しておきます。

  • tree v2.0.0 から、FD 3が開いていると標準出力の替わりにそちらにデータをJSONで流すよ
  • 今迄通りの挙動をさせるには、 3>&- 等でFD 3を閉じてあげる必要があるよ
  • passはこれに対処済みだけどまだリリースされてないのでユーザーサイドでは使えないよ
  • 現状passを呼び出す際は必ず pass 3>&- としておけば対策できるよ

原因

treeの2.0.0リリースにて入った破壊的変更が原因です。

treeのCHANGELOGから引用させてもらうと

Output un-indented JSON on file descriptor 3 ("stddata")
automatically if file descriptor 3 is present (currently Linux only.)
Maybe switch to BSON.

ざっくりと訳すと「Linuxに於いては、File Descriptor 3が開いている場合はそこに整形されていないJSONを書き込むようになりました。BSONになるかもしれない」とのことです。
pass自体も普通に使っていれば問題ないのですが、 git credential を呼んだ際はどうしてか 沢山ファイルディスクリプタが使用されます。

私の環境下では以下のファイルディスクリプタが開いていました

  • 0 (標準入力)
  • 1 (標準出力)
  • 2 (標準エラー出力)
  • 255
  • 3
  • 4
  • 5
  • 6

そう、ここで3番があったんですね...

対策

必要なのは、treeコマンドのファイルディスクリプタの3番を閉じるだけです。

上流で行われている対策

実はpassではこれに対して対策が取られており、commit:eea24967にてコミットされています。

しかし、2022/02/07現在ではこれはまだリリースされていないためエンドユーザーは使用できません。(まぁgitでmasterから取って来て使うことは勿論出来ますが)
はやいとこリリースされてほしい...

現状できること

passを呼び出す際にfd 3を塞ぎます。

pass 3>&-

とすることで、passプロセスのファイルディスクリプタ3番を閉じることができます。passを使用する何らかのスクリプトを書いている場合、当面はこうするのがよさそうです。

おまけ: >&- の意味

元は [n]>&word という形です。 n で指定された、出力のファイルディスクリプターを word で指定された番号のファイルディスクリプターに複製します。 そして、 もし word- であるなら 指定したファイルディスクリプターを閉じます。

man:bash(1) Redirection 節の Duplicating File Descriptors に説明があります。

おまけ2: あるプログラムが開いているファイルデイスクリプターの一覧を取得する

Linuxでは、カーネルがあらゆる情報を procファイルシステム に擬似的なファイルとして書き込んでくれています。 (man:proc(5))

大抵はこれが /proc にマウントされているはずです。 各プロセスの情報は /proc/${PID}/ ディレクトリ下に生成され、ファイルディスクリプターの情報は /proc/${PID}/fd ディレクトリ下に生成されます。bashに於いて、実行中のプロセスのPIDは $$ で取得できるので:

ls /proc/$$/fd

参考

Discussion