プログラムがクラッシュした場合に一時ファイルが残らないようにしたいです。
UNIX は、ファイルを削除した後でも開いたままにできるという点で優れています。
ファイルを開いたらすぐに削除し、それから処理が遅い場合は、プログラムがクラッシュしても、ユーザーがファイルをクリーンアップする必要がなくなる可能性が高くなります。
シェルでは次のようなものがよく見られます:
generate-the-file -o the-file
[...loads of other stuff that may use stdout or not...]
do_slow_processing < the-file
rm the-file
しかし、プログラムがクラッシュした場合は、rm
ユーザーがクリーンアップする必要がありますthe-file
。
Perl では次のことができます:
open(my $filehandle, "<", "the-file") || die;
unlink("the-file");
while(<$filehandle>) {
# Do slow processing stuff here
print;
}
close $filehandle;
ファイルは開かれるとすぐに削除されます。
シェルに同様の構造はありますか?
答え1
これは、csh、tcsh、sh、ksh、zsh、bash、ash、sash でテストされています。
echo foo > the-file
(rm the-file; cat) < the-file | do_slow_processing
do_other_stuff
または、ご希望の場合は:
(rm the-file; do_slow_processing) < the-file
do_other_stuff
興味深いことに、これは FIFO でも機能します。
mkfifo the-fifo
(rm the-fifo; cat) < the-fifo | do_slow_processing &
echo foo > the-fifo
これは、何かが書き込まれるまでリーダーがブロックされるためです。
答え2
generate-the-file > the-file
exec 5< the-file
rm the-file
...
do_slow_processing 0<&5
ノート:
- 実行可能ファイルなしでexecを実行する必要があるため、シェル自体の記述子に影響します。
- fd 9までしか利用できません
- ファイル名が必要な場合は、/proc/self/fd/X を使用できます。このインターフェイスは UNIX の種類間で移植可能ではありません (ただし、おそらく問題なく動作します)。
- fdを再度読み込もうとすると(例えば を2回呼び出す
cat 0<&5
)、EOFに到達しているため失敗します。巻き戻すか、以下で読み込んでこれを克服する必要があります。/proc/self/fd/X
- ほとんどの場合、上記のように実際のファイルを使わずに、単純な
generate-the-file | do_slow_processing
アップデート:
OP は、generate-the-file
stdout に出力が生成されない可能性があると述べています。これにはいくつかの慣用句があります。
- 出力ファイルを指定します
-
。出力ファイル名として - を指定するのが通例で、これはstdoutを意味します。これはPOSIX.1-2017 で承認:ガイドライン13: 読み取りまたは書き込み用に開かれるファイルを表すためにオペランドを使用するユーティリティの場合、「-」オペランドは、標準入力 (または出力ファイルが指定されていることがコンテキストから明らかな場合は標準出力) または - という名前のファイルのみを意味するために使用する必要があります。
(明示的に定義されているユーティリティ以外の場合は実装定義ですが、ツールでサポートされている可能性は高いですgenerate-the-file
)
/dev/stdout
またはを使用して/proc/self/fd/1
ください。OSによって異なります。/dev/stdin、/dev/stdout、/dev/stderr はどの程度移植可能ですか?プロセス置換を使用します。bash ではファイル名として書き込むことができます
>(process substitution)
。例:wget -O >(rot13 > 質問.txt)https://unix.stackexchange.com/q/579535/70346
これはすべてのシェルで動作するわけではなく、fd ファイル名に対する OS のサポートが必要です。
答え3
シェルではbash
、クリーンアップを処理するには、trap
組み込みの EXIT を使用します (シェル内から次のようにbash
入力しますhelp trap
)。
trap 'rm temp-file' EXIT
この機能はシェルにも存在しdash
、sh
最近の Linux ディストリビューションでは頻繁にエイリアス化されています。