シェルで使用される前に一時ファイルをクリーンアップできますか?

シェルで使用される前に一時ファイルをクリーンアップできますか?

プログラムがクラッシュした場合に一時ファイルが残らないようにしたいです。

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-filestdout に出力が生成されない可能性があると述べています。これにはいくつかの慣用句があります。

  • 出力ファイルを指定します-。出力ファイル名として - を指定するのが通例で、これはstdoutを意味します。これはPOSIX.1-2017 で承認:

    ガイドライン13: 読み取りまたは書き込み用に開かれるファイルを表すためにオペランドを使用するユーティリティの場合、「-」オペランドは、標準入力 (または出力ファイルが指定されていることがコンテキストから明らかな場合は標準出力) または - という名前のファイルのみを意味するために使用する必要があります。

(明示的に定義されているユーティリティ以外の場合は実装定義ですが、ツールでサポートされている可能性は高いですgenerate-the-file)

これはすべてのシェルで動作するわけではなく、fd ファイル名に対する OS のサポートが必要です。

答え3

シェルではbash、クリーンアップを処理するには、trap組み込みの EXIT を使用します (シェル内から次のようにbash入力しますhelp trap)。

trap 'rm temp-file' EXIT

この機能はシェルにも存在しdashsh最近の Linux ディストリビューションでは頻繁にエイリアス化されています。

関連情報