open: permission denied 错误源于操作系统拒绝访问,主因包括权限不足、用户组不匹配、挂载选项限制或 SELinux/AppArmor 拦截;应使用 os.IsPermission 判断,而非字符串比对,并注意预检查需遍历父目录执行权限。
Go 程序调用 os.Open、os.Create 或 os.OpenFile 时抛出 open /path/to/file: permission denied,说明操作系统拒绝了当前进程对目标路径的访问请求。这不是 Go 自身的错误,而是底层 syscall 返回了 EACCES 或 EPERM。常见原因包括:目标文件/目录没有读/写/执行权限、进程运行用户不属于目标文件所属组、挂载点设置了 noexec 或 nosuid、SELinux/AppArmor 等强制访问控制策略拦截。
不能直接比对错误字符串,必须用标准库提供的类型判断函数。Go 的 os.PathError 实现了 error 接口,且 os.IsPermission 能准确识别权限类错误(包括 EACCES 和 EPERM),而 os.IsNotExist 或 os.IsExist 不会误判

file, err := os.Open("/etc/shadow")
if err != nil {
if os.IsPermission(err) {
log.Printf("无权读取 /etc/shadow:%v", err)
// 这里可降级处理,比如跳过或提示用户 sudo
return
}
if os.IsNotExist(err) {
log.Printf("文件不存在:%v", err)
return
}
log.Printf("其他 I/O 错误:%v", err)
return
}
defer file.Close()
如果需要在打开前预判是否可行(比如构建友好报错或自动修复),可用 os.Stat 获取 os.FileInfo,再通过 Mode() 提取权限位。注意:仅检查目标路径本身权限不够,还需逐级检查父目录的执行(x)权限(Linux/macOS 下进入目录需 x 权限)。
fi.Mode().Perm() & 0400 判断是否可读(user read)fi.Mode().Perm() & 0200 判断是否可写(user write)filepath.Dir(path) 向上遍历每一级,检查其 Mode().Perm() & 0100(user execute)os.Stat 本身也可能因权限不足失败,需先处理该错误生产环境应规避直接操作 /etc、/var/log 等系统路径。更健壮的做法是:
os.UserHomeDir() 或 os.TempDir() 构建用户隔离路径XDG_CONFIG_HOME(Linux)或 os.Getenv("APPDATA")(Windows)log.SetOutput 重定向到用户可写位置,而非固定 /var/log/myapp/
sudo 启动,并在文档中注明权限需求权限错误往往不是代码逻辑问题,而是部署上下文缺失——比如容器内没挂载宿主机目录、CI runner 用户无权访问缓存路径、systemd service 文件没设 ReadWritePaths=。查错时优先确认运行时环境,而不是改 Go 代码。