You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node 20/21中fs.writeFileSync写入TMPDIR触发EACCES权限错误

Node.js 20/21中fs.readFileSync使用a+标志创建文件导致权限错误的问题

问题概述

一段读取并修改JSON文件的代码在Node.js 18中可正常运行,但在Node.js 20/21中执行时触发EACCES权限错误——目标文件被创建后权限为0000,完全没有读写权限,导致后续写入操作失败。

错误原因

Node.js 20+版本对fs模块的文件权限处理逻辑做了变更:当通过fs.readFileSync以a+模式打开不存在的文件时,不再自动继承系统umask对应的默认文件权限,导致生成的文件权限为0000。而Node.js 18中a+模式创建文件时,会自动应用符合预期的默认权限(通常为0o644)。

解决方案

方案1:显式指定文件权限

在fs.readFileSync的配置中添加mode参数,明确指定文件的权限(例如0o644,代表所有者读写、组和其他用户只读):

import fs from 'fs'
import path from 'path'
import os from 'os'

function modify(fsPath, key, value) {
  const dir = path.dirname(fsPath)
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })
  
  // 显式指定mode参数,确保创建的文件拥有正确权限
  let content = fs.readFileSync(fsPath, { 
    encoding: 'utf8', 
    flag: 'a+',
    mode: 0o644 
  })
  content = content || '{}'
  const jsonContent = JSON.parse(content)
  jsonContent[key] = value
  fs.writeFileSync(fsPath, JSON.stringify(jsonContent), { encoding: 'utf8' })
}

// 修正路径,匹配报错中的/test/foo.json
const p = path.join(os.tmpdir(), 'test', 'foo.json')
modify(p, 'key', 'foobar')

方案2:提前创建文件并设置权限

先判断文件是否存在,若不存在则先创建带正确权限的空文件,再进行读取操作:

import fs from 'fs'
import path from 'path'
import os from 'os'

function modify(fsPath, key, value) {
  const dir = path.dirname(fsPath)
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })
  
  // 提前创建文件(若不存在),确保权限正确
  if (!fs.existsSync(fsPath)) {
    fs.writeFileSync(fsPath, '{}', { encoding: 'utf8', mode: 0o644 })
  }
  
  const content = fs.readFileSync(fsPath, { encoding: 'utf8' })
  const jsonContent = JSON.parse(content || '{}')
  jsonContent[key] = value
  fs.writeFileSync(fsPath, JSON.stringify(jsonContent), { encoding: 'utf8' })
}

const p = path.join(os.tmpdir(), 'test', 'foo.json')
modify(p, 'key', 'foobar')

方案3:替换文件打开模式

改用r+模式打开文件,但需提前确保文件存在(若不存在则先创建),避免r+模式下文件不存在时报错:

import fs from 'fs'
import path from 'path'
import os from 'os'

function modify(fsPath, key, value) {
  const dir = path.dirname(fsPath)
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })
  
  if (!fs.existsSync(fsPath)) {
    fs.writeFileSync(fsPath, '{}', { encoding: 'utf8' })
  }
  
  // 使用r+模式读取文件
  const content = fs.readFileSync(fsPath, { encoding: 'utf8', flag: 'r+' })
  const jsonContent = JSON.parse(content || '{}')
  jsonContent[key] = value
  fs.writeFileSync(fsPath, JSON.stringify(jsonContent), { encoding: 'utf8' })
}

const p = path.join(os.tmpdir(), 'test', 'foo.json')
modify(p, 'key', 'foobar')

内容的提问来源于stack exchange,提问作者fannheyward

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 07:05:16