OS X、bash:開いているファイル記述子では機能しませんが、猫では機能しません


10

私が取り組んでいるbashスクリプト(UbuntuとOS Xで実行する必要があります)では、何百ものコマンドの出力をファイルにリダイレクトする必要があります。それらすべてに
追加&>...するのではなく、単に

exec 9>&1
exec 5<>/tmp/some-file.txt
exec 1>&5

これまでのところ良好ですが、これらすべてのコマンドの途中で、ファイル記述子を開いたまま、これまでに書き込まれたすべてを読み取る必要があります。
今、Ubuntuで私は簡単にできます

cat /dev/fd/5

または

tee </dev/fd/5

ただし、OS Xでは何も出力されません(コマンドはすぐに終了します)。
ただし、less両方を使用してファイルの内容を確認できます。
私は使用することで上記の効果(両方のOSで動作する)を達成できます

less /dev/fd/5 | tee

しかし、それはハックのようです。

では、なぜOS X lessで表示catできないものを表示できるのでしょうか?(または、すべてのBSDの子孫が影響を受けますか?)
または、何か間違ったことをしていますか?

回答:


13

OS Xでは、Linuxを除いてサポートされているすべてのシステム/dev/fd/xと同様に、opening はを行うようなものdup(x)であり、結果のfdはfd xと同じオープンファイルの説明を指し、特にファイル内のオフセットは同じになります。

Linuxはここでは例外です。Linuxでは、/dev/fd/xはへのシンボリックリンクで/proc/self/fd/xあり/proc/self/fd/x、fd xで開いているファイルへの疑似シンボリックリンクです。Linuxでを実行するとopen("/dev/fd/x", somemode)、で開いたのと同じファイルに新しい開いたファイルの説明が表示されxます。取得した新しいfdは、fd xとはまったく関係ありません。特に、オフセットはファイルの先頭にあり(O_APPENDもちろん、ファイルを開く場合を除く)、モード(読み取り/書き込み/追加...)はfd xのモードとは異なる場合があります(取得することもできます) fd xにあるものとはかなり異なるもの、たとえば反対のモードでパイプを開くときのパイプのもう一方の端)(つまり、open()できないソケットなどでは機能しません)。

したがって、Linuxでは、

exec 5<> file
echo test >&5

fd 5のオフセットはファイルの最後にあります。もし、するなら

cat <&5

あなたは何も得ません。

それでもあなたがするとき:

cat /dev/fd/5

あなたが見るtestためcatの新しい読み取り専用にfdを取得しfile5をfdに無関係。

他のシステムでは、

cat /dev/fd/5

cat fd 5の複製であるfdを取得するため、ファイルの最後にオフセットが残っています。

それはで動作する理由は、lessいくつかの理由のため、ということであるlesslseek()(ないファイルの先頭にそのFDにlseek(1); lseek(0)ファイルがシークであるかどうかを判断するため)。

ここでは、おそらく異なるfdをオフセットにしたい場合は、読み取り用と書き込み用のfdが必要です。

exec 5< file 9>&1 > file

それとも、もしまだそこにファイルを再度開く、または実行する必要がありますlseek()ようにless行います。

ksh93そして、zsh組み込みの持つ唯一のシェルですlseek()けれどもオペレーター:

cat <&5 <#((0)) # ksh93
{sysseek 0; cat} <&5 # zsh, zmodload zsh/system to enable that builtin

または:

cat /dev/fd/5 5<#((0))  # ksh93
sysseek -u 5 0; cat /dev/fd/5 # zsh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.