追加されているファイルを移動しても安全ですか?


28

fs.appendFile行を追加するために使用するnode.jsプロセスがありますfile.log。行ごとに約40文字の完全な行のみが追加されます。たとえば、呼び出しはlikeでfs.appendFile("start-end")、2つの呼び出しはfs.appendFile("start-")andのようではありませんfs.appendFile("end")。このファイルを移動するfile2.logと、行が部分的に失われたりコピーされたりしないことを確認できますか?

回答:


36

ファイルシステムの境界を越えてファイルを移動しない限り、操作は安全です。これは、»移動«が実際に行われるメカニズムによるものです。

mv同じファイルシステム上のファイルの場合、ファイルは実際には変更されず、ファイルシステムのエントリのみが変更されます。

$ mv foo bar

実際に次のようなことをします

$ ln foo bar
$ rm foo

これにより、名前が付けられたファイル(実際にはファイルシステムエントリが指すiノード)のハードリンク(2番目のディレクトリエントリ)が作成され、エントリが削除されます。現在、を削除するときに、のiノードを指す2番目のファイルシステムエントリがあります。古いエントリを削除しても、実際にはiノードに属するブロックは削除されません。foobarfoofoofoofoo

開いているファイルハンドルがファイルシステムエントリではなくファイルのiノードを指しているため、プログラムはとにかくファイルに追加します。

注:プログラムが書き込みと書き込みの間にファイルを閉じて再度開くと、古いファイルシステムエントリで新しいファイルが作成されることになります。

ファイルシステム間の移動:

ファイルシステムの境界を越えてファイルを移動すると、事態がgetいものになります。以来、この場合、あなたは、あなたのファイルの一貫性維持持つことを保証することができませんでしたmv、実際に希望

  • ターゲットファイルシステムに新しいファイルを作成します
  • 古いファイルの内容を新しいファイルにコピーします
  • 古いファイルを削除する

または

$ cp /path/to/foo /path/to/bar
$ rm /path/to/foo

それぞれ

$ touch /path/to/bar
$ cat < /path/to/foo > /path/to/bar
$ rm /path/to/foo

アプリケーションの書き込み中にコピーがファイルの終わりに到達するかどうかによっては、新しいファイルに半分の行しかない場合があります。

さらに、アプリケーションが古いファイルを閉じて再度開かない場合、削除されたように見えても、古いファイルへの書き込みを続けます。カーネルは開いているファイルを認識し、ファイルシステムエントリを削除しますが、アプリケーションが開いているファイルハンドルを閉じるまで、古いファイルのiノードと関連するブロックは削除されません。


3
参考までに、Unixの初期バージョンにはrename()システムコールがありませんでした。ので、元のバージョンはmv実際にlink()ハードリンクを作成するために呼び出し、その後unlink()に元の名前を削除しました。rename()これをカーネルに原子的に実装するために、FreeBSDに追加されました。
バーマー14年

申し訳ありませんが、何file-system bordersですか?
laike9m

1
@ laike9m-ファイルシステムの境界は、単純なファイルシステムが、ディスクドライブのような1つのメモリデバイス上の1つのパーティションに存在する必要があるという事実を指します。ファイルシステム内のファイルの名前を変更すると、変更されるのはディレクトリエントリ内のファイルの名前だけです。ほとんどのLinuxファイルシステムがそうであるように、それはまだ同じiノードを持っています-iノードに基づいたファイルシステムにあった場合- ただし、ファイルを別のファイルシステムに移動する場合、実際のデータを移動する必要があり、ファイルは新しいファイルシステムから新しいiノードを取得します。これにより、これが発生したときに進行中だったファイルの操作が中断されます。
ジョー14年

9

あなたはnode.jsを使用していると言うので、ファイルの名前を変更するためにfs.rename()(またはfs.renameSync())を使用していると思います。このnode.jsメソッドは、 rename(2)システムコール、ファイル自体には一切触れず、ファイルシステムにリストされている名前を変更するだけです。

" rename()ファイルの名前を変更し、必要に応じてディレクトリ間で移動します。ファイルへの他のハードリンク(link(2)を使用して作成された)は影響を受けません。。oldpathのも影響を受けません。"

特に、上記で引用した最後の文に注意してください。これは、開いているファイル記述子(プログラムがファイルへの書き込みに使用するものなど)は、名前が変更された後も引き続き指し示します。したがって、ファイルへの書き込み中にファイル名を変更しても、データの損失や破損はありません。


Andreas Weiseが答えで指摘しているように、rename(2)システムコール(したがってfs.rename() node.js内)はファイルシステムの境界を越えて機能しません。したがって、この方法でファイルを別のファイルシステムに移動しようとすると失敗します。

Unix mvコマンドは、エラーを検出し、代わりにコンテンツを新しいファイルにコピーして元のファイルを削除することでファイルを移動することにより、この制限を隠そうとします。残念ながら、このようなファイルを移動することはありません、それが書き込まれている間、ファイルを移動した場合のリスクデータの損失を。したがって、同時に書き込まれる可能性のあるファイルの名前を安全に変更する場合は使用しないでくださいmv(少なくとも、新しいパスと古いパスが同じファイルシステム上にあることを絶対に確認する必要があります)。

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