リンクされたコマンドはアトミックですか?

リンクされたコマンドはアトミックですか?

常にファイルに書き込むプロセスがあり、rootでファイルを制御したい場合は、次のようにします。

sudo rm somefile; sudo touch somefile

これら2つのコマンドの間にファイルに追加のプロセスを追加できますか?それでは、その間に他のコマンドが実行されないようにする方法はありますか?

答え1

リンクされたコマンドラインは基本的に小さなシェルスクリプトです。通常のfork + execプロセスを使用して最初のコマンドを実行し、終了するのを待ってから、同じ方法で2番目のコマンドを実行します。これら2つのコマンドの間では、シェルは記録と処理にランダムな時間を費やします。この間、一般的な複数の処理が発生し、他の任意のプロセスが他の任意の操作を実行できます。だから答えは「いいえ」です。 (これを行うと、ディレクトリエントリはsomefile消えますが、ファイル自体は閉じられるまで(プロセスによって開かれたため)まだ存在します。それまでは、ファイルが使用するディスク容量を回復しません。同時に、このtouchコマンドは同じ名前とパスを持つ関連ない新しいファイルを生成します。

ファイルの所有権をrootに変更するには、これを行うことができますsudo chown root:root somefile(これが開かれたファイルハンドルを持つプロセスにどのような影響を与えるかはわかりません)。現在のファイルの内容を削除するには、次のことを試してくださいtruncate -s 0 somefile(実行中のプロセスは現在空のファイルに追加され続けます)。他のことなら何をしたいのかを明確にしてください。

答え2

いいえ。コマンドrmの後にtouchコマンドが来るのはまったくアトミックではありません。 2 つのコマンド間の時間間隔はかなり長いです。おそらくミリ秒の範囲です。その間に多くのことが起こることがあります。運が悪いと、sudoの資格情報が期限切れになることがあります。

単一のプログラムを呼び出しunlinkopen呼び出すと、競合期間が短くなりますが、まだ発生する可能性があります。

より安全なアプローチは、一時的な名前で新しいファイルを作成し、renameシステムコールを使用することです。システムコールを使用して名前を「オーバーライド」することは、原子性が保証されますrename。これはおよびtouchを使用して達成できますmv

ただし、書き込みのために古いファイルを開いたプロセスは、古いファイルが削除された後でも長い間ファイルに書き込むことができます。unlinkこれは削除されたファイルと削除されたファイルの両方で発生しますrename

答え3

プロセスが読み取り用にファイルハンドルを開くと、所有権または権限で何をするかは問題ではありません。プロセスは引き続きファイルにアクセスできます。ファイルを削除することもでき、プロセスはファイルハンドルを介してそのファイルにアクセスできます。

権限をファイルハンドルを取得するためのコントロールゲートと考えてください。

ファイルを自動的に生成するには、次の操作をしないでください。

sudo rm somefile
sudo touch somefile

以下を考慮することができます。

sudo touch anotherfile
sudo perl -e "rename 'anotherfile', 'somefile'"

(使用したいがシステムコールが呼び出されることを保証するステートメントがsomefile見つかりません。anotherfilemv -frename(2)


たぶん「制御ファイル」の意味を説明するために質問を更新することができます。あなたはXYの問題ここで。

答え4

いいえ、しかし

sudo rm somefile; sudo touch somefile

ほとんどの場合安全です。

ほとんどのプロセスはファイルを開き、取得したファイル記述子を使用してファイルの内容にアクセスします。

プロセスがshでファイルを開く場合:

 exec 3>somefile

その後、他のプロセスは自由にsomefileのリンクを解除(=削除)することができ、最初のプロセス(この場合は3)がsomefileを開いたファイル記述子は現在の不確実な状態ファイルであるsomefileの元の内容を参照し続けます。

sudo touch somefile

関連付けられていない新しい somefile が作成され、古い somefile が開いており、ファイル記述子のみを使用してそれを参照するすべてのプロセスは影響を受けません。これは、現在不確実なステータス文書内の他のファイルを参照しているためです。

非ルートプロセスが名前でファイルを参照しようとすると、新しいファイルがルートの所有であるため、EPERMエラーが発生します。

Linuxには、同じユーザー(ルートなど)の複数のプロセスがファイルを破損するのを防ぐために、必須および推奨ファイルロック機能があります。flockアドバイザリファイルをロックするためのシェルスクリプトでこのコマンドを使用できます(詳細はマンページを参照)。

関連情報