【问题标题】:Node.js sporadically failing to write file with: Error: ENOENT, open 'filename'Node.js 偶尔无法写入文件:错误:ENOENT,打开“文件名”
【发布时间】:2014-02-19 15:00:29
【问题描述】:

我正在开发一个访问文件系统的 node.js 应用程序。在我的测试中,我注意到谷歌无法为我回答的一些非常奇怪的问题。

我的代码在 95% 的情况下都能正常工作,但是,有时我会收到以下错误:“错误:ENOENT,打开 'test.Q3rax'”,其中 test.Q3rax 是随机生成的文件名。该文件应该是可写的,如果我再次运行我的代码,并在其中硬编码文件名,它就可以正常工作。

这是失败的代码:

npJSON.prototype._writeFile = function(newData) {
    if (!this.loaded)
        throw "ERROR: npJSON._writeFile() was called before any data was loaded.";
    var stringToWrite = JSON.stringify(newData);
    fs.writeFile(this.fileName,stringToWrite, function(err) {
        if (err)
            throw err;
    });
};

编辑:为了澄清,这就是我生成随机文件名的方式:

var filename = 'test.' + getRandomText(5,6);

function getRandomText(numberOfCharactersLow, numberOfCharactersHigh) {
    var numbChar = getRandomInt(numberOfCharactersLow, numberOfCharactersHigh);
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
    var returnText = '';
    for (var i = 0; i < numbChar; i++) {
        returnText += possible.charAt(getRandomInt(0, 62));
    }
    return returnText;
}

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

【问题讨论】:

  • fileName 是否可能包含斜杠(或反斜杠)? ENOENT,在这种情况下,很可能意味着您尝试将文件写入的目录不存在。
  • 这是我最初看到错误时所希望的,但后来我开始输出文件名以确保它不是,并且文件名都是有效的。我将更新我的帖子以包括我如何生成文件名。
  • 您是否有多个进程访问同一个文件?我在运行单元测试时遇到了类似的问题,我的问题是我自己的竞争条件:stackoverflow.com/questions/10368806/node-js-readfile-woes
  • 可能是这种情况,我努力避免这种情况,但我可能在某些时候错过了它。我已经有一段时间没有发生这种情况了,即使我毫不拖延地循环它以尝试强制错误。老实说,这很不幸,因为我想解决它而不是让它消失。

标签: javascript node.js


【解决方案1】:

您可能会遇到这样一个事实,即 Node 中的文件在异步写入时不是使用 O_SYNC 写入的。这意味着您可能会在内核将文件刷新到磁盘之前尝试访问该文件。这里还有一点阅读内容(在标题fs.writeFile() 下):http://www.daveeddy.com/2013/03/26/synchronous-file-io-in-nodejs/

编辑:这里有一个例子来有力地证明这个问题:

var fs = require('fs');
var fname = '/tmp/fs.' + process.pid + '.tmp';
var buf = new Buffer(1024);
buf.fill('a');

fs.writeFile(fname, buf, function(err) {
  console.log(err);
});

try {
  fs.readFileSync(fname);
} catch(e) {
  console.log(e.stack);
}

process.on('exit', function() {
  try { fs.unlinkSync(fname); } catch(e) {}
});

// Output:
// Error: ENOENT, no such file or directory '/tmp/fs.31281.tmp'

【讨论】:

  • 我将不得不将其归结为这一点,我仔细检查并确信只有一个流访问该文件。感谢您提供有见地的链接
【解决方案2】:

我的猜测是您有多个流同时访问该文件。我会看看锁定:

https://github.com/71104/rwlock

【讨论】:

    猜你喜欢
    • 2012-11-12
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    相关资源
    最近更新 更多