web-dev-qa-db-ja.com

出力をファイルにリダイレクトすると、ファイルにロックが適用されますか?

コマンドがある場合

$ ./script >> file.log

それは2回呼び出され、最初の呼び出しが終了する前に2番目の呼び出しが発生すると、どうなりますか?

最初の呼び出しは出力ファイルに排他ロックを取得しますか?その場合、2番目のスクリプトは書き込みを試みたときに失敗しますか、それともシェルは出力を受け入れ(スクリプトの終了を許可)してエラーをスローしますか?

または、ログファイルは2回書き込まれますか?

30
user20672

追加を意味する>>を使用しているため、各インスタンスからの出力の各行は、発生した順に追加されます。

スクリプト出力が1\nから5\nまでを出力し、それぞれの間に1秒の遅延があり、インスタンス2が2.5秒後に開始されると、次のようになります。

1
2
1
3
2
4
3
5
4
5

だからあなたの質問に答える:いいえ。

18
bahamat

Unixシステムは、概して必須ロックを回避します。カーネルがユーザープログラムによる変更に対してファイルをロックする場合がいくつかありますが、それが別のプログラムによって単に書き込まれている場合はそうではありません。プログラムがファイルに書き込んでいるため、UNIXシステムはファイルをロックしません。

スクリプトの同時インスタンスが互いにつま先を踏まないようにする場合は、 flocklockfileなどの明示的なロックメカニズムを使用する必要があります。

追加するファイルを開くと、>>は、各プログラムが常にファイルの最後に書き込むことが保証されています。したがって、複数のインスタンスの出力が互いに上書きすることは決してなく、順番に書き込む場合、それらの出力は書き込みと同じ順序になります。

起こりうる悪いことは、インスタンスの1つが複数の出力チャンクを書き込み、それらが一緒に出力されることを期待している場合です。 1つのインスタンスによる連続した書き込みの間に、他のインスタンスが独自の書き込みを実行する場合があります。たとえば、インスタンス1がfooを書き込み、インスタンス2がhelloを書き込み、インスタンス2のみがbarを書き込む場合、ファイルにはfoohellobarが含まれます。

プロセスは、writeシステムコールを呼び出すときに、ファイルに効率的に書き込みます。 writeへの呼び出しはアトミックです。writeを呼び出すたびに、他のプログラムによって中断されないバイトシーケンスが書き込まれます。多くの場合、writeへの1回の呼び出しで効果的に書き込むデータの量には制限があります。サイズが大きい場合、データの先頭のみが書き込まれ、アプリケーションはwriteを再度呼び出す必要があります。さらに、多くのプログラムは バッファリング を実行します。これらのプログラムはデータをメモリ領域に蓄積し、このデータを1つのチャンクに書き込みます。一部のプログラムは、完全な行または他の意味のある分離後に出力バッファーをフラッシュします。このようなプログラムを使用すると、行が長すぎない限り(最大で数キロバイト、これはOSによって異なります)、行全体が中断されないことが期待できます。プログラムが意味のある場所でフラッシュせず、バッファサイズのみに基づいてフラッシュする場合、あるインスタンスから4kB、次に別のインスタンスから4kB、次に最初のインスタンスから4kBのように表示される場合があります。