9

我有一个 Node.js 应用程序,它将一些配置数据存储在一个文件中。如果更改某些设置,配置文件将写入磁盘。

目前,我正在使用一个简单的fs.writeFile.

现在我的问题是:当 Node.js 在写入文件时崩溃时会发生什么?是否有机会在磁盘上有损坏的文件?或者 Node.js 是否保证文件是以原子方式编写的,以便旧版本或新版本都有效?

如果没有,我该如何实施这样的保证?有没有这方面的模块?

4

3 回答 3

10

在写入文件时 Node.js 崩溃会发生什么?是否有机会在磁盘上有损坏的文件?或者 Node.js 是否保证文件是以原子方式编写的,以便旧版本或新版本都有效?

Node 仅在系统调用上实现了一个(瘦)异步包装器,因此它不提供任何关于写入原子性的保证。事实上,fs.writeAll反复调用,fs.write直到所有数据都被写入。你是对的,当 Node.js 崩溃时,你最终可能会得到一个损坏的文件。

如果没有,我该如何实施这样的保证?有没有这方面的模块?

我能想出的最简单的解决方案是用于 FTP 上传的解决方案:

  1. 将内容保存到具有不同名称的临时文件中。
  2. 当内容写入磁盘时,将临时文件重命名为目标文件。

手册页说 rename保证保留 newpath 的实例(在 Linux 或 OSX 等 Unix 系统上)。

于 2013-06-11T17:09:22.783 回答
7

fs.writeFile,就像fs模块中的所有其他方法一样,都是作为标准 POSIX 函数的简单包装器实现的(如docs中所述)。

深入研究 nodejs 的代码,可以看到定义了所有包装器的fs.js使用fs.c进行所有文件系统调用。更具体地说,该write方法用于写入缓冲区的内容。事实证明,写的POSIX 规范明确表示:

原子/非原子:如果在一个操作中写入的全部量没有与来自任何其他进程的数据交错,则写入是原子的。当有多个写入器向单个读取器发送数据时,这很有用。应用程序需要知道可以以原子方式执行的写入请求有多大。此最大值称为 {PIPE_BUF}。本卷 IEEE Std 1003.1-2001 没有说明超过 {PIPE_BUF} 字节的写入请求是否是原子的,但要求 {PIPE_BUF} 或更少字节的写入应该是原子的。

所以看起来写起来很安全,只要缓冲区的大小小于 PIPE_BUF。这是一个依赖于系统的常量,因此您可能需要在其他地方检查它。

于 2013-06-11T17:27:15.770 回答
7

write-file-atomic会做你需要的。它写入临时文件,然后重命名。那是安全的。

于 2016-01-31T23:17:57.020 回答