【问题标题】:How to open a file with exclusive file access in node?如何在节点中打开具有独占文件访问权限的文件?
【发布时间】:2021-03-21 14:51:51
【问题描述】:

在 Windows 上,我正在寻找一种以独占方式打开文件的方法。 MSDN 记录了一个名为CreateFile 的函数,其中dwShareMode0

https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea

具体来说,我正在寻找一种文档在此处说明的方式:

阻止其他进程在请求删除、读取或写入访问权限时打开文件或设备。

有谁知道包装此功能的内置或 npm 包?

【问题讨论】:

  • nodejs 中的 Windows 似乎不支持此类功能。虽然mode 参数中存在fs.open() 所需的所有标志,但该文档表示,控制其他人可能拥有的访问权限的位并未在Windows 上实现。因此,对于某些模块来实现这一点,他们必须实现自己的整个文件系统访问,而不依赖于fs.open(),这是我从未见过的。为什么这没有在 Windows 上实现,我不知道底层操作系统肯定包含所需的功能。
  • 让我修改我以前的 cmets。使用fs-ext 可能支持独占访问。几年前有很多关于它在 Windows 上无法运行的错误的喋喋不休,但现在这个问题被标记为已解决,所以它现在可以工作了。

标签: node.js windows npm


【解决方案1】:

如果您可以成功构建模块附加组件fs-ext,它将在 Windows 上运行。我必须在我的系统上安装 Python 并将其放入路径中,然后才能成功安装和构建。一旦我这样做了,我就能够运行这个测试,它验证了一个子进程不允许读取或写入我有一个羊群的文件:

// open-exclusive.js
const fs = require('fs');
const fsp = fs.promises;
const child = require('child_process');
const { promisify } = require('util');
const execP = promisify(child.exec);
const flock = promisify(require('fs-ext').flock);

const exclusive = fs.constants.S_IRUSR | fs.constants.S_IWUSR | fs.constants.S_IXUSR;

async function run() {
    const fHandle = await fsp.open("./temp.txt", "r+", exclusive);
    await flock(fHandle.fd, 'ex');
    await fHandle.write("Goodbye", 0);
    console.log('parent finished write');

    const { stdout, stderr } = await execP("node open-exclusive-child.js");
    console.log('stdout:', stdout);
    console.error('stderr:', stderr);
    console.log('parent done exec');
    await fHandle.close();
    return "good";
}

run().then(result => {
    console.log(result);
}).catch(err => {
    console.log(err);
});

子进程文件open-exclusive-child.js

const fs = require('fs');
const fsp = fs.promises;

async function run() {
    const fHandle = await fsp.open("./temp.txt", "r");
    let buf = Buffer.alloc(10);
    await fHandle.read(buf, 0, 10, 0);
    await fHandle.write("Hello", 0);
    console.log('child: finished write');
    await fHandle.close();
    return "child good"
}

run().then(result => {
    console.log(result);
}).catch(err => {
    console.log(err);
});

当我运行node open-exclusive.js 时,父进程会打开它,flock 成功,然后子进程将无法读取或写入文件。孩子显然可以“打开”文件,但在尝试读取或写入文件时出现 EBUSY 错误。

事实上,flock 也是同样的过程:

const fs = require('fs');
const fsp = fs.promises;
const { promisify } = require('util');
const execP = promisify(child.exec);
const flock = promisify(require('fs-ext').flock);

const exclusive = fs.constants.S_IRUSR | fs.constants.S_IWUSR | fs.constants.S_IXUSR;

async function run() {
    const fHandle = await fsp.open("./temp.txt", "r+", exclusive);
    await flock(fHandle.fd, 'ex');
    await fHandle.write("Goodbye", 0);
    console.log('parent finished write');

    const fHandle2 = await fsp.open("./temp.txt", "r");
    const buf = Buffer.alloc(10);
    console.log("About to read from fHandle2");
    let bytes = await fHandle2.read(buf, 0, 10, 0);
    console.log(bytes);
    await fHandle2.close();
    await fHandle.close();
    return "good";
}

run().then(result => {
    console.log(result);
}).catch(err => {
    console.log(err);
});

当我运行它时,我会在控制台中得到它:

node open-exclusive.js
parent finished write
About to read from fHandle2
[Error: EBUSY: resource busy or locked, read] {
  errno: -4082,
  code: 'EBUSY',
  syscall: 'read'
}

【讨论】:

  • 这就是完美的答案!之后我会为此添加赏金。我可以编译它,它也可以在这里工作。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2020-02-10
  • 2010-11-23
  • 2021-08-02
  • 1970-01-01
  • 1970-01-01
  • 2017-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多