使用 ChatGPT、Codex 修改项目以后,经常会碰到一种很典型的问题:
自己电脑上构建、测试都正常,一提交到 CI,就直接报 Permission denied。
常见表现包括:
- 本地脚本可以直接执行;
- GitHub Actions、GitLab CI 或其他 Runner 一运行就失败;
- Shell 脚本提示没有执行权限;
- 构建目录无法写入;
- Docker 里运行正常,CI 容器里却报权限错误;
- Windows 本地没问题,Linux Runner 一执行就出错;
- Codex 明明只改了几行代码,CI 却突然开始报权限问题。
这类问题很多时候不是业务代码错了。
真正需要检查的是:
CI环境里的用户、文件权限和本地开发环境并不一样。
一、本地能执行,不代表CI里的文件也有执行权限
例如项目里有一个脚本:
deploy.sh
你在自己电脑上执行完全正常。
但 CI 里运行:
./deploy.sh
却提示:
Permission denied
很可能是因为这个文件在 Linux 环境里没有:
执行权限。
也就是文件虽然存在,但 Runner 没有权限直接把它当程序运行。
所以第一步不是继续改脚本内容,而是确认:
这个文件到底有没有 executable 权限。
二、最常见的问题是chmod只在本地改了,却没有进入Git
很多人会在本机执行:
chmod +x deploy.sh
然后发现:
本地终于能运行了。
但提交代码以后,CI仍然报错。
原因可能是:
Git没有记录这次文件模式变化。
尤其是不同操作系统之间协作时更容易出现。
可以检查 Git 是否真正记录了文件执行位变化,而不是只确认:
我电脑上已经能执行。
否则换一台Runner,问题依然存在。
三、Windows开发、Linux CI特别容易出现差异
Windows 对执行权限的处理方式和 Linux 不一样。
所以开发者在 Windows 本地经常感觉:
文件就在这里,为什么不能运行?
但 Linux Runner 会严格检查:
- owner;
- group;
- read;
- write;
- execute。
于是同一份项目:
Windows开发正常,Linux CI直接Permission denied。
这类问题应该优先考虑环境权限差异,而不是怀疑 ChatGPT、Codex 改坏了业务逻辑。
四、不只是“执行文件”,目录也可能没有写权限
还有一种常见情况:
脚本本身可以执行,但构建过程中需要写入:
- dist
- build
- coverage
- tmp
- cache目录
- 日志目录
Runner用户对这些目录没有写权限。
于是可能出现:
EACCES
或者:
Permission denied
这种时候问题不在命令能不能启动。
而在于:
当前进程没有权限创建、修改或删除目标文件。
所以看到权限报错时,一定要继续确认:
到底是哪一个文件或目录被拒绝了?
五、先确认CI到底使用哪个用户运行
本地开发时,你可能一直使用自己的系统账户。
但 CI Runner 可能使用:
- runner;
- node;
- ubuntu;
- www-data;
- 非root容器用户。
如果某个目录属于另外一个用户,当前 Runner 就可能无法访问。
所以排查时最好同时确认:
当前执行用户 + 目标文件所有者 + 文件权限。
不要只盯着报错命令本身。
六、Docker里的USER也很容易造成权限问题
例如 Dockerfile 里为了安全使用:
USER node
这通常是好事。
但如果前面某一步创建的目录仍然属于:
root
后面的 node 用户就可能无法写入。
于是本地开发容器可能因为运行方式不同没暴露问题,到了CI构建环境却直接失败。
特别要检查:
- COPY 后文件属于谁;
- 工作目录是谁创建的;
- Build阶段和Runtime阶段用了什么用户;
- Volume挂载以后权限有没有变化。
七、挂载目录和缓存也可能把权限问题带回来
有时 CI 第一次运行正常,第二次突然失败。
原因可能不是代码变化,而是:
缓存或挂载目录保留了错误的文件所有者。
比如第一次某个步骤使用 root 创建缓存。
后面的普通用户复用这个缓存时,就没有权限修改。
所以权限问题如果具有:
第一次正常、后面偶发失败
这种特征,也要检查:
- dependency cache;
- build cache;
- workspace;
- artifact目录。
八、不要一看到Permission denied就直接全部chmod 777
这是一种很常见但不推荐的做法。
把整个项目改成:
777
确实可能暂时让 CI 跑过去。
但同时也掩盖了真正的权限设计问题。
更合理的处理方式是:
只给真正需要执行或写入的文件、目录最小权限。
例如:
脚本需要执行,就补执行权限。
构建目录需要写入,就调整该目录的owner或write权限。
不要为了跑通一次CI,把整个工作区都放开。
九、可以按这个顺序排查
ChatGPT、Codex 修改项目后,如果本地正常、CI 报 Permission denied,建议按下面顺序检查:
第一步:定位具体报错文件或目录。
不要只看最后一行。
第二步:确认脚本执行权限。
检查是不是 .sh、CLI 文件没有 executable 权限。
第三步:确认Git有没有记录权限变化。
避免只在本地 chmod。
第四步:确认Runner用户。
它到底以哪个账户运行。
第五步:检查目标目录所有者和写权限。
尤其是 build、cache、coverage、tmp。
第六步:如果用了Docker,检查USER和COPY产生的文件权限。
第七步:检查缓存和挂载目录。
确认旧文件没有留下错误owner。
十、可以直接这样让ChatGPT、Codex排查
以后遇到这种情况,可以直接告诉 ChatGPT、Codex:
请不要先修改业务代码。先根据CI日志定位具体是哪个文件或目录出现Permission denied,再检查脚本执行权限、Git是否记录file mode、Runner当前用户以及目录owner。如果使用Docker,请检查USER、WORKDIR、COPY和挂载目录权限;如果问题偶发,再检查CI缓存是否保留了错误的文件所有者。不要直接使用chmod 777,优先给最小必要权限。
这样通常比:
本地能跑,为什么CI失败?
更容易快速缩小范围。
最后
ChatGPT、Codex 修改项目以后,本地正常但 CI 一直报 Permission denied,很多时候真正的问题不是:
代码不能运行。
而是:
换到Runner环境以后,执行用户和文件权限发生了变化。
最有效的排查链路应该是:
报错文件 → 执行权限 → Git File Mode → Runner用户 → 目录Owner → Docker USER → 缓存与挂载。
先确认:
到底是谁,在访问哪个文件时,被系统拒绝了?
这个问题一旦搞清楚,权限类 CI 故障通常就不会再靠反复改代码碰运气。
持续更新 ChatGPT、Codex、大模型开发与 AI 编程实战内容,更多技术内容和稳定订阅渠道欢迎搜索关注「仙逆GPT」。




