
私のプログラムがクラッシュした場合、一時ファイルを避けたいと思います。
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を実行する必要があるため、シェル自体の記述子に影響します。
- 最大9つのfdのみが提供されます。
- ファイル名が必要な場合は、/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を意味)を受け入れます。これはPOSIX.1-2017によって承認されました:ガイドライン13: 読み取りまたは書き込みのために列ファイルを表すためにオペランドを使用するユーティリティの場合、「-」オペランドは標準入力(または出力ファイルが指定されていることがコンテキストで明確である場合は標準出力)を表すためにのみ使用する必要があります。 )またはファイル名は-です。
generate-the-file
(明確に定義されたユーティリティ以外のユーティリティの場合、実装によって定義されますが、ツールがそれをサポートする可能性が高いです。)
オペレーティングシステムに応じて、または
/dev/stdout
を使用してください。/proc/self/fd/1
/dev/stdin、/dev/stdout、および/dev/stderrの移植性はどのくらいですか?プロセス置換を使用します。 bashを使用すると、
>(process substitution)
ファイル名を書き込むことができます。たとえば、wget -O >(rot13 > Question.txt)https://unix.stackexchange.com/q/579535/70346
これはすべてのシェルで機能するわけではなく、オペレーティングシステムがfdファイル名をサポートする必要があります。
答え3
bash
シェルでクリーンアップを処理する方法は、trap
組み込みのEXIT(bash
シェルに入力help trap
)を使用することです。
trap 'rm temp-file' EXIT
dash
この機能はシェルにも存在し、sh
最新のLinuxディストリビューションではエイリアシングとも呼ばれます。