fs.appendFile
に行を追加するnode.jsプロセスがあります。たとえば、2つの呼び出しの代わりにfile.log
それぞれ約40文字の行全体を追加します。このファイルを次の場所に移動すると、行が失われたり部分的にコピーされないようにできますか?fs.appendFile("start-end")
fs.appendFile("start-")
fs.appendFile("end")
file2.log
答え1
ファイルシステムの境界を越えてファイルを移動しない限り、操作は安全です。これは、「移動」が実際に行われる方法であるダイナミクスによるものです。
ファイルが同じファイルシステムにある場合、mv
ファイルは実際に触れることなくファイルシステムエントリのみが変更されます。
$ mv foo bar
実際には、次のことを行います。
$ ln foo bar
$ rm foo
これにより硬いファイル(実際にはファイルシステムエントリが指すinode)へのリンク(2番目のディレクトリエントリ)のfoo
名前が指定され、bar
エントリfoo
が削除されます。これで、削除時にinodeをfoo
指す2番目のファイルシステムエントリがあるので、古いエントリを削除してもfoo
実際foo
にそのinodeに属するブロックは削除されません。
開かれたファイルハンドルがファイルシステムエントリではなくファイルのinodeを指すので、プログラムはとにかくファイルに幸せに追加されます。
メモ:プログラムが書き込みの間にファイルを閉じて再度開くと、次のエラーが発生します。新しい以前のファイルシステムエントリを使用してファイルが作成されました!
ファイルシステム間の移動:
ファイルシステムの境界を越えてファイルを移動すると、状況が悪くなる可能性があります。この場合、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
アプリケーションへの書き込み中にコピーがファイルの終わりに達したかどうかに応じて、新しいファイルには行が半分しかありません。
また、アプリケーションが古いファイルを閉じて再度開くことができない場合は、古いファイルが削除されたように見えても、古いファイルに書き込まれます。カーネルはどのファイルが開いているかを知っており、ファイルシステムエントリを削除しても削除されます。それ。古いファイルの inode と関連ブロックは、アプリケーションが開いたファイルハンドルを閉じるまで削除されません。
答え2
node.jsを使うとしたら、次のものを使うとしましょう。fs.rename()
(またはfs.renameSync()
)ファイルの名前を変更します。このnode.jsメソッドは、以下を使用するように文書化されています。名前変更(2)何らかの方法でファイル自体に触れることなく、単にファイルシステムにリストされている名前を変更するシステムコール:
」名前を変更する()ファイル名を変更し、必要に応じてディレクトリ間を移動します。ファイルへのその他のハードリンク(次を使用して作成)協会(2))には影響しません。オープンファイル記述子古い道影響を受けません。 」
上記の最後の文に特別な注意を払ってください。開いているファイル記述子(たとえば、プログラムがファイルに書き込むために使用する説明)は、名前を変更した後も引き続きそれを指すと言います。したがって、ファイルの書き込み中にファイル名を変更しても、データの損失や破損は発生しません。
Andreas Weiseが書いたように彼の答え、 rename(2) システムコール (したがってfs.rename()
Node.js で) はファイルシステムの境界を越えて動作しません。したがって、この方法でファイルを別のファイルシステムに移動しようとすると失敗します。
Unixmv
コマンドはエラーを検出し、代わりにコンテンツを新しいファイルにコピーし、元のファイルを削除してファイルを移動することによってこの制限を非表示にします。残念ながら、このようなファイルを移動することはするファイルの書き込み中にファイルを移動すると、データが失われる可能性があります。したがって、同時に書き込むことができるファイルの名前を安全に変更するには、次の手順を実行する必要があります。いいえmv
(または少なくとも新しいパスと古いパスが同じファイルシステムにあることを確認する必要があります)。