web-dev-qa-db-ja.com

>で同じファイルにリダイレクトする複数のプロセス

これは「追加して上書きしない方法」の質問ではありません。 2つのコマンドの出力を組み合わせたファイルを探していません。それは私が犯した間違いであり、システムがなぜそれをしたのかを理解したいと思います

完了するのに長い時間がかかり、データ(数秒ごとに1行ずつ)をstdoutに出力するコマンド(リモートsshコマンドライン)を使用するので、ファイルにリダイレクトします。

command > file.out &

リモートセッションが切断されることがありますが、コマンドはバックグラウンドで実行され続けます。私はこれを知らなかったので、最初のコマンドが完了する前に同じコマンドをもう一度実行します

command > file.out &

両方のプロセスが終了すると、(このサイトでいくつかの回答を読んだ後)両方のコマンドの行がめちゃくちゃになっている単一のファイルができると期待しますが、出力ファイルには2つの実行のうちの1つからの出力しかありません。

ファイルに両方の出力が絡み合っていないのはなぜですか(コメント here で警告されています)?最終的なファイルは2つの出力のどちらに属しますか?

編集:

説明されているように、質問の1つを削除しました(出力ファイルが書き込み用にロックされていないのはなぜですか?) here

3
golimar

>リダイレクトを使用して書き込み用にファイルを開くと、ファイルは切り捨てになります。つまり、完全に空になります。ただしnotは削除され、再作成されます。

あるコマンドがファイルの切り捨てから始まり、それに何かを書き込む場合、別のコマンドが同じことを行う場合、ファイル内の最初のコマンドの位置は変更されません。これは、2つの独立した位置で同じファイルに書き込む2つのコマンドがあることを意味し、1つは他の出力を上書きする可能性があります書き込みの順序と書き込まれるデータの量によって異なります

そのため、はい、ファイル内のデータは、両方のプログラムからの出力の絡み合った混乱である可能性がありますが、ファイルへの書き込みの順序、および書き込まれたデータの量と切り捨てのタイミングによって異なりますファイル。

2つのコマンドからのデータを絡み合わせる例を次に示します。

#!/bin/sh

( { echo hello; sleep 2; echo world; } | cat >file ) &
sleep 1
echo 123 >file &

wait

これはこのスクリプトで何が起こるかです:

  1. 最初のコマンドは、ファイルを書き込み用に開き、切り捨てます。それにhello\nを書き込みます。
  2. 1秒後、2番目のコマンドはファイルを切り捨て、123\nを書き込みます。この時点で、最初のコマンドのファイルポインターは、まだオフセットでファイルを指しています。
  3. 最初のコマンドは、ファイルへのworld\nの書き込みを続行します。

結果は、途中に一連のヌル文字を含むファイルです。

$ hexdump -C file
00000000  31 32 33 0a 00 00 77 6f  72 6c 64 0a              |123...world.|
0000000c

Nuls(上記の出力の00)は、最初のコマンドのファイルポインターが2番目のコマンドのファイルの切り捨てによってリセットされなかったため、「穴」が作成されたことが原因です。 2番目のコマンドは123\nのみを書き込みましたが、より多くのデータを書き込んだ場合、nulは上書きされます。

$ hexdump -C file
00000000  31 32 33 35 36 37 77 6f  72 6c 64 0a              |123567world.|
0000000c

ここでは2番目のコマンドecho 1234567890を作成しましたが、ファイルには1234567のみが残っています。これは、最初のコマンドが、2番目のコマンドが書き込みを完了した後のファイルポインターがあった場所でworld\nの書き込みを続行するためです。

8
Kusalananda