MacOで同じプロセス代替ファイルに繰り返し書き込む

MacOで同じプロセス代替ファイルに繰り返し書き込む

次のbash-fuコードはLinuxではうまく動作しますが、MacOSではクラッシュします。

files="foo bar"

echo PROG 1
for file in $files
do
  echo $file | tee -a tempfile.txt
done

sort -u tempfile.txt

echo PROG 2
function trick {
  for file in $files
  do
    echo $file | tee -a $1
  done
}

trick >(sort -u)

エラーは次のとおりです。

PROG 1
foo
bar
bar
foo
PROG 2
tee: /dev/fd/63: Bad file descriptor
foo
tee: /dev/fd/63: Bad file descriptor
bar

LinuxでもPROG 2同じ行がPROG 1エラーなしで作成されます。 MacOSでは、パイプハンドルが閉じているか継承されていないようです。

上記は、問題を再現する最小限の例です。実際、私は接続出力とリダイレクトハンドルをたくさん扱っています。何か霊的なもの

function trick {
  for file in $files
  do
     echo $file | tee -a $1 | grep -Eo "^.."
  done
}

trick >(sort -u | sed 's|o|x|g')

このコードは Bash 4.1 では動作しませんが、複数のディストリビューション (Arch、Ubuntu、Debian) の Bash 4.4 では動作します。

ベストアンサー1

macOSには非常に古いバージョンが付属していますbash。バグ(プロセスによって置き換えられたファイル記述子がteeこのコンテキストで呼び出される前に閉じられた)が最新バージョンで修正されました。 Linuxで/dev/fd/xbash 3.2を使用すると、同じ問題が発生します(実装が異なるため、他のエラーメッセージが表示されます)。

zshここではorを代わりに使用できますksh93bashとにかくここは避けるのがいいと思います。プロセスの交換中にプロセスを待ちません。(zshがこれを待っており、ksh93に通知することができますwait)。

最新バージョン(作成時の4.4.12)にも、bash次のようないくつかのバグがあります。

$ bash -c 'eval cat <(echo test)'
test # OK but:
$ bash -c 'eval "echo foo;cat" <(echo test)'
foo
cat: /dev/fd/63: No such file or directory
$ bash -c 'eval f=<(echo test) "; cat \$f"'
cat: /dev/fd/63: No such file or directory

一部はまだ次のパイプによってトリガされます。

$ cat file
echo "$1"
cat "$1"
$ bash -c 'source ./file <(echo test)'
/dev/fd/63
test  # OK but:
$ cat file2
echo "$1" | wc -c
cat "$1"
$ bash -c 'source ./file2 <(echo test)'
11
cat: /dev/fd/63: No such file or directory

1 パイプが存在する場合、bash はファイル記述子を閉じます。より短いプレーヤー:

$ bash -c 'f() { :; cat "$1"; }; f <(echo OK)'
OK
$ bash -c 'f() { :|:; cat "$1"; }; f <(echo test)'
cat: /dev/fd/63: No such file or directory

おすすめ記事