【问题标题】:NodeJS fs.unlinkSync not freeing up hard-drive space on aws ec2 serverNodeJS fs.unlinkSync 没有释放 aws ec2 服务器上的硬盘空间
【发布时间】:2021-03-15 22:39:00
【问题描述】:

我在 Elastic Beanstalk 上有一个 NodeJS 应用程序。

我正在下载大量大型 zip,打开并处理它们,然后通过 fs.unlinkSync 删除 zip 文件

测试时我看到文件被删除,但显然 unlink 在进程使用它时实际上不会释放空间?

如何指示 fs 释放内存分配?

我正在通过

写文件
let writeStream = fs.createWriteStream(file.name);
writeStream.on('finish', () => {
  // a bunch of logic that eventually returns a promise

在它的解析/拒绝中

fs.unlinkSync(file.name)

我已经完成了,这是我唯一一次触摸文件,其他所有内容都已关闭。我需要等待 writeStream 关​​闭的其他事件吗?

--全面解释工作流程

for (let i = 0; i < records.length; i++) {
  await processZip(records[i]);
  fs.unlinkSync(records[i].name);
}

processZip 方法内部

return new Promise(async (resolve, reject) => {

  var readStream = this.s3Access.getObjectStream(guid);
  let writeStream = fs.createWriteStream(file.name);
  readStream.pipe(writeStream);

  writeStream.on('finish', () => {
    resolve();
  }
}

【问题讨论】:

  • 你需要让 gc 完成它的工作。使用nextTick 并确保释放包含内存的变量

标签: node.js


【解决方案1】:

根据NodeJS docsunlinkSync()正在调用C/C++ API调用unlink

这是文档所说的here

unlink() 从文件系统中删除一个名称。如果那个名字是 最后一个文件链接并且没有进程打开该文件,该文件是 已删除,并且它正在使用的空间可供重复使用。

如果名称是文件的最后一个链接,但任何进程仍然有 文件打开,文件将一直存在,直到最后一个文件 引用它的描述符已关闭。

如果名称引用了符号链接,则删除该链接。

如果名称涉及套接字、FIFO 或设备,则其名称为 已删除,但打开对象的进程可以继续使用 它。

对于要删除的文件,基本上应该关闭所有链接。

尝试考虑可能使用您尝试删除的文件的其他进程(使用 fs.open/openSync() 打开但未关闭的文件等)

更新

processZip返回的promise解析成功后,文件好像被删除了。

如果 promise 被拒绝(即异步函数中抛出错误),删除文件也会很有用。

for (let i = 0; i < records.length; i++) {
  try {
    await processZip(records[i]);
  } finally {
    // delete file after success or error
    fs.unlinkSync(records[i].name);
  }
}

另外'error' 事件处理程序可以添加到processZip 中的两个流中。

我在stream.pipe()docs找到了这个注释,可能和问题有关:

一个重要的警告是,如果Readable 流在处理过程中发出错误,Writable 目标不会自动关闭。如果发生错误,则需要手动关闭每个流以防止内存泄漏。

return new Promise(async (resolve, reject) => {

  var readStream = this.s3Access.getObjectStream(guid);
  let writeStream = fs.createWriteStream(file.name);
  readStream.pipe(writeStream);

  writeStream.on('finish', () => {
    resolve();
  }

  readStream.on('error', err => {
    readStream.end();
    writeStream.end();
    reject(err);
  }

  writeStream.on('error', err => {
    readStream.end();
    writeStream.end();
    reject(err);
  }
}

【讨论】:

  • 嗨 Vitalii 感谢您的建议,我浏览并确保没有其他链接或文件引用,并更新了我的问题以显示
  • 嗨 Joshua,我在文档中找到了有关错误处理的额外信息,并在我的回复中为您的代码添加了错误处理建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-24
  • 2021-05-07
  • 2020-02-02
  • 2016-03-30
  • 1970-01-01
  • 2014-12-07
  • 1970-01-01
相关资源
最近更新 更多