ファイルに継続的に書き込むプロセスがあり、ルートでファイルを制御したい場合は、次のようなことができます。
sudo rm somefile; sudo touch somefile
追加プロセスがこれらの2つのコマンドの間にファイルに追加することは可能ですか?もしそうなら、その間に他のコマンドが実行されないようにする方法はありますか?
ファイルに継続的に書き込むプロセスがあり、ルートでファイルを制御したい場合は、次のようなことができます。
sudo rm somefile; sudo touch somefile
追加プロセスがこれらの2つのコマンドの間にファイルに追加することは可能ですか?もしそうなら、その間に他のコマンドが実行されないようにする方法はありますか?
回答:
チェーンされたコマンドラインは基本的に小さなシェルスクリプトです。通常のfork + execプロシージャを使用して最初のコマンドを実行し、それが終了するのを待ってから、2番目のコマンドを同じ方法で実行します。2つのコマンドの間には、シェルが簿記と処理にかかる任意の時間があり、その間に通常のマルチプロセッシングが行われ、他の任意のプロセスが他の任意のことを行う可能性があります。したがって、答えは「いいえ」です。(実際にこれを行うとsomefile、ファイルのディレクトリエントリは消えますが、ファイル自体は(プロセスによって開かれているため)閉じられるまで残ります。ファイルが使用するディスク領域は、それが発生するまで再利用されません。 、touchコマンドは、同じ名前とパスで、無関係な新しいファイルを作成します。
ファイルの所有権をrootに変更したい場合は、変更してくださいsudo chown root:root somefile(ファイルハンドルが開いているプロセスにどのように影響するかはわかりません)。現在のファイルの内容を破棄したい場合は、試してくださいtruncate -s 0 somefile(実行中のプロセスは、現在空のファイルに追加し続けます)。それ以外の場合は、おそらく何をしたいかを明確にします。
chownsomefileを使用しても、somefileへのファイルハンドルを持つプロセスには影響しません。
exec 3>somefile; sudo chmod 0600 somefile; echo hello world >&3; sudo cat somefile; exec 3>&-。
いいえ。rmコマンドの後にコマンドを続けても、touchアトミックではありません。2つのコマンド間の時間が長くなります-おそらくミリ秒の範囲です。その間、たくさんのことが起こりえます。運が悪いと、sudo資格情報の有効期限が切れることもあります。
unlinkとをopen呼び出す単一のプログラムでは、レースのウィンドウがはるかに短くなりますが、それでも発生する可能性があります。
より安全な方法は、一時的な名前で新しいファイルを作成し、renameシステムコールを使用することです。renameシステムコールで名前を「上書き」すると、アトミックであることが保証されます。これはtouch、およびを使用して実現できますmv。
ただし、古いファイルを書き込み用に開いたプロセスは、削除された後もずっとファイルに書き込み続けることができます。これは、を使用unlinkして削除されたファイルとを使用して削除されたファイルの両方に当てはまりますrename。
プロセスが読み取り用のファイルハンドルを開いたら、所有権や権限をどのように処理しても問題ありません。プロセスは引き続きファイルにアクセスできます。ファイルを削除することもでき、プロセスはファイルハンドルを介してファイルにアクセスし続けることができます。
アクセス許可をファイルハンドルを取得するためのコントロールゲートと見なします。
アトミックにファイルを作成したい場合は、これを行う代わりに:
sudo rm somefile sudo touch somefile
あなたはこれを考えることができます:
sudo touch anotherfile
sudo perl -e "rename 'anotherfile', 'somefile'"
これはアトミックにと置き換えsomefileられanotherfileます。(私は使用したいと思いましたがmv -f、これがrename(2)システムコールを呼び出すことを保証するステートメントを見つけることができません。
質問を更新して、「ファイルを制御する」という意味を説明することもできます。ここにXY問題がある可能性があります。
mv -fを取得するために使用しrename(2)ます。あなたはそれが正しいlnそれはいつも使っているので、しませんlink(2)アトミックに置き換えることはできませんシステムコールを、。 ln -fちょうどないunlink(2)最初のターゲットに。
ln脳にいた。rename(2)関与することを保証する方法がわからなかったため、さらに掘り下げるには遅すぎました
mv「同等のアクションを実行する」 ことを保証しrename(old, new)ます。 pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html。 宛先が書き込み可能でないかのmv -fようにmv -i動作しますが、最初にリンクを解除するような場所cp -fやln -f場所ではありません。
いいえ、でも
sudo rm somefile; sudo touch somefile
ほとんどの状況で安全です。
ほとんどのプロセスはファイルを開き、取得したファイル記述子を使用してファイルの内容にアクセスします。
プロセスがshでsomefileを開いた場合:
exec 3>somefile
次に、別のプロセスがsomefileを自由にリンク解除(=削除)し、somefileが最初のプロセスによって開かれたファイル記述子(この場合は3)は引き続きsomefileの元のコンテンツを参照します。これは現在リンボのファイルです。
sudo touch somefile
新しい無関係なsomefileを作成し、古いsomefileを開いているすべてのプロセスがファイル記述子を使用してそれを参照しているだけで、別のファイルを参照しているため、影響を受けません。
非ルートプロセスがsomefileを名前で参照しようとすると、新しいsomefileがルート所有であるため、EPERMエラーが発生します。
同じユーザー(rootなど)の下の複数のプロセスがファイルを破損しないようにしたい場合は、Linuxが必須および推奨ファイルロックを備えています。flockシェルスクリプトでコマンドを使用して、アドバイスファイルをロックできます(詳細については、マンページを参照してください)。