Node.js , Windows, fs.open() — нежелательный флаг только для чтения во вновь созданном файле

#node.js #windows #fs

#node.js #Windows #fs

Вопрос:

У меня возникли проблемы с пониманием того, почему Windows создает новый файл с установленным атрибутом только для чтения. Мне нужны эксклюзивные права на запись с произвольным доступом к файлу, который я буду использовать как простое хранилище данных на основе файлов. Я в порядке с другими процессами, считывающими из него, но я хочу, чтобы только один процесс мог записывать в него.

Я пробовал несколько разных вариантов флагов открытия, но независимо от того, что я делаю, Windows, похоже, устанавливает атрибут только для чтения в файле. Таким образом, после закрытия файла попытки повторно открыть его для записи завершаются неудачей. Я понимаю, что я мог бы вручную попытаться манипулировать атрибутом после факта, но это наоборот. Я не хочу, чтобы атрибут отображался в первую очередь. Когда я закрываю файл, он должен быть безопасным для кого-то другого, чтобы открыть для записи.

 FS.open(filePath   '.lock', 'w ', 6, (err, fd) => {
  if (err) console.log('failed to open lock file', err);
  else {
    console.log('successfully opened lock file');
    setTimeout(() => {
      FS.close(fd, () => {
        console.log(`closed lock file`);
        setTimeout(() => {
          console.log(`attempt reopening the file...`);
          FS.open(filePath   '.lock', 'w ', 6, (err, fd) => {
            if (err) console.log('failed to open lock file', err);
            else {
              console.log(`file closed successfully`);
              FS.closeSync(fd);
            }
          });
        }, 500);
      });
    }, 500);
  }
});
  

Вывод:

 successfully opened lock file
closed lock file
attempt reopening the file...
failed to open lock file [Error: EPERM: operation not permitted, open 'D:salixtest.data.lock'] {
  errno: -4048,
  code: 'EPERM',
  syscall: 'open',
  path: 'D:\dev\test.data.lock'
}
  

нежелательный атрибут только для чтения

Как вы можете видеть, файл, похоже, имеет установленный атрибут только для чтения, даже после закрытия файла.

Ответ №1:

TLDR: установите режим файла 0o644 таким образом, чтобы вы могли читать и записывать в него, но другие могут только читать. Установка значения just 6 не дает вам (владельцу файла) никаких разрешений на чтение или запись и, следовательно, проблема с EPERM, с которой вы сталкиваетесь, когда пытаетесь открыть его самостоятельно после его создания.

Мне кажется, что ваши значения режима файла неверны. Когда вы устанавливаете для него значение 6 , это определяет чтение и запись для других, но не определяет чтение и запись для себя.

Здесь есть довольно хорошее описание того, как они работают.

В основном вам нужны три восьмеричных значения. Самый левый для вас (владельца). Средний флаг предназначен для группы. Правильный для других. Таким образом, 0o644 владелец может читать и записывать, а группа и другие только читают.

В качестве тестового жгута, чтобы попробовать разные режимы, я использовал эту программу:

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

function delay(t) {
    return new Promise(resolve => {
        setTimeout(resolve, t);
    });
}

async function run() {
    const mode = 0o644;
    const fileHandle1 = await fsp.open("test.lock", "w ", mode);
    console.log("file open first time");
    await fileHandle1.close();
    console.log("file closed first time");

    await delay(500);

    const fileHandle2 = await fsp.open("test.lock", "w ", mode);
    console.log("file open second time");
    await fileHandle2.close();
    console.log("file closed second time");
}

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

К ВАШЕМУ сведению, node.js имеет именованные константы для различных разрешений, которые могут сделать код более читаемым в долгосрочной перспективе, чем просто использование восьмеричных цифр.

Комментарии:

1. Хм, все еще не вижу никакой эксклюзивности. У меня есть два отдельных файловых дескриптора с поддержкой записи, успешно открытых для одного и того же файла блокировки.

2. @NathanRidley — Два файловых дескриптора с поддержкой записи в одном процессе? Или в разных процессах. Наверное, я не понимаю, какую проблему вы пытаетесь решить. Я решил проблему, из-за которой вы не могли открыть свой собственный файл. Это то, что я думал, что вы пытались сделать. Эксклюзивность в вашем процессе — это другой набор флагов.

3. Да, первая часть решена, спасибо 🙂 Общая картина заключалась в том, что я хотел простой способ гарантировать, что одновременно можно открывать только один дескриптор записи в файл. Будь то в одном процессе или в разных процессах, я хотел убедиться, что никогда не было более одного автора. С тех пор, как я опубликовал это, я нашел правильный-lockfile в npm, поэтому, думаю, я воспользуюсь этим.

Ответ №2:

Аргумент file mode 6 создает файл только для чтения.

Используйте 0o600 , если вы хотите читать / записывать для пользователя.

Комментарии:

1. Спасибо за ответ. Я пробовал 0o600 и 0o200, но в обоих случаях нет права на запись.

2. Режимы файлов устанавливают только права доступа к файлам, поэтому устраняется часть проблемы «только для чтения». Я думал, что эксклюзивность записи была установлена по умолчанию в Windows, когда процесс открывает файл для записи?

3. Я бы тоже так подумал, но почему-то у меня есть два файловых дескриптора, открытых по одному и тому же пути, оба с разрешениями на запись, и оба сообщают об успехе попыток записи в файл.