Linuxで「>>」を使用すると、bashはO_APPENDでファイルを開きますか?


38

使用するとecho 1234 >> some-file、ドキュメントに出力が追加されると記載されています。

私の推測では、いくつかのファイルが存在しない場合、O_CREATは新しいファイルを作成します。もしを>使用し、その後、O_TRUNCは、既存のファイルが切り捨てられます。

次の場合>>:ファイルはO_WRONLY(またはO_RDWR)として開かれ、終了を求めてO_APPENDをシミュレートして書き込み操作が行われますか?または、ファイルがO_APPENDとして開かれ、追加を確実に行うためにカーネルに残されますか?

出力ファイルがNFSマウントポイントからのものである場合、コンサーバープロセスがエコーによって挿入されたいくつかのマーカーを上書きしているため、私はこれを求めています&NFSドキュメンテーションはO_APPENDがサーバーでサポートされていないため、クライアントカーネルがそれを処理する必要があると述べています。私はconserverプロセスがO_APPENDを使用していると思いますが>>、Linux でbashが確実でないため、ここで質問します。


12
NFSの問題O_APPENDは、サポートされていないということではありません。問題はエミュレートされていることです。ローカルファイルシステムでは、開いた同じファイルに書き込む複数のプロセスがO_APPEND 互いのデータを上書きすることはありません。NFSでは、O_APPEND書き込み前に最後までシークすることでエミュレートされ、競合状態の可能性が残ります。NFSでこれを回避する方法はありません。各パラレルライターは、独自のファイルを書き込む必要があります。これを回避する唯一の方法は、NFSサーバー上でサーバープロセスをセットアップし、ロガーをにログ記録させ|nc server port、サーバーに受信データをログに追加させることです。
Guntram Blohmは

@GuntramBlohm、+1、確認ありがとう。基本的に、ファイルに対して1つのライタープロセスのみを使用することをお勧めします。他のすべてのライタープロセスはこのプロセスを実行します。
-Prem

たくさんの良い答え、どの答えを受け入れるべきかわからない。最初のBruce Edigerは、O_APPENDが使用されることを示しました。次に、Random832は、これが規格に記載されていることを示しました。最後に、Eric Renoufは同じ答えのソースコードを示しました。3つの視点すべてが最終的な全体像に追加されます。
Prem

6
要するに、NFSは多くのバグであり、使用すべきではありません。
R ..

2
ええ、しかし、O_EXCLが発明されたとき、私たちはすでにその方法を学びました。
ケビン

回答:


60

私はこれを実行しました:strace -o spork.out bash -c "echo 1234 >> some-file"あなたの質問を理解するため。これは私が見つけたものです:

open("some-file", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

echoコマンドを実行したディレクトリに「some-file」という名前のファイルが存在しませんでした。


50

これはBashで行われるだけでなく、標準で要求されています。

Single Unix Specificationから

付加された出力リダイレクトにより、指定されたファイル記述子での出力のために、wordの展開から名前が得られたファイルが開かれます。ファイルは、POSIX.1-2008のSystem Interfacesボリュームで定義されているopen()関数がO_APPENDフラグで呼び出されたかのように開かれます。ファイルが存在しない場合は作成されます。

したがって、POSIX準拠のシェルはそれを行う必要があります。一部のUNIXシステムでは、/bin/sh非POSIX Bourneシェルであってもよい(Bourneシェルは、もともと前に書かれたO_APPEND発明された)、そして利用可能なPOSIXシェルは、典型的にはkshとして利用できるようになる、shそのようなSolarisののような異なる経路の場所に/usr/xpg4/bin


2
興味深いことに、それを行わないシェルの1つがBourneシェルです。Bourneシェルは、最後までO_TRUNCおよびlseek()なしで開きます。これは、O_APPENDフラグがに追加される前に書き込まれたためopen()です。>>それ自体は、その前身であるトムソンシェルによって導入されました。
ステファンシャゼル

1
@StéphaneChazelasまた、さまざまなバージョンのCシェルソースを調べましたが、O_APPENDフラグは4.3BSD-Renoまで導入されませんでした。
Random832

「あたかも」のように書かれているので、別の方法で実装することはできません(ただし、同じ観測可能な効果が得られます)。標準 O_APPENDの使用を必要とするようには見えません、「あたかも」のように動作するものです。
トーマス

1
@Thomas O_APPENDについて文書化されたすべての動作を取得することを意味します。つまり、書き込みごとに最後に再配置します。「あたかも」は、たとえば、非伝統的なUnixプラットフォームでopen()関数を実際に呼び出す以外の方法で開くことができるようにするための単なる標準的な言い回しです。
Random832

+1は、この動作が標準に含まれていることを示しています。
-Prem

32

ソースを見ると、O_APPENDが使用されています。make_cmd.c710-713行のbash 4.3.30の場合:

case r_appending_to:                /* >>foo */
case r_append_err_and_out:          /* &>> filename */
  temp->flags = O_APPEND | O_WRONLY | O_CREAT;
  break;

+1。ソースコードの観点から回答を表示します。
プレム

19

straceローカル(NFS以外)ファイルシステムで使用することを調査してみましょう。

$ strace -eopen -- bash -c "echo foo >> /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

$ strace -eopen -- bash -c "echo foo > /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3

つまり他のシェル、dashdashshbusyboxのの」とmksh同じように振る舞います。

このオプション-e open-e trace=openopen()システムコールのみをトレースすることを意味します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.