Linux 脚本已有执行权限,运行仍报 Permission denied
Linux 脚本已有执行位仍报 Permission denied 时,检查实际路径的 noexec 挂载限制,区分解释器读取与直接执行,并选择迁移目录或调整挂载策略的处理方式。
脚本已经有执行位,直接运行却被拒绝:
$ ./job.sh
bash: ./job.sh: Permission denied
如果重复 chmod +x 没有变化,而把脚本交给解释器读取时能够运行,应检查脚本所在挂载点是否带有 noexec。文件权限与挂载选项是两层限制:执行位允许,并不能抵消挂载点禁止直接执行的规则。
本文适用于 Linux 上可读取的普通脚本文件。Permission denied 本身不足以确认 noexec;父目录不可访问、解释器权限或其他访问控制也可能产生相同错误。先查实际路径的挂载状态。
查文件所在的挂载点,而不是只查根分区
以下以 /srv/jobs/job.sh 为脚本路径示例,替换成实际文件的绝对路径:
ls -l /srv/jobs/job.sh
findmnt --target /srv/jobs/job.sh --output TARGET,SOURCE,FSTYPE,OPTIONS
第一条用于核对文件类型、所有者和权限位,第二条查这个路径实际落在哪个已挂载文件系统。/srv、/home 或更深一层目录可能单独挂载;只查看 / 的选项会漏掉这些限制。
若 OPTIONS 中包含 noexec,当前挂载禁止直接执行该挂载上的文件。此时继续增加文件执行权限不会解除限制,更不需要把文件改成所有人可写的 777。
若文件是符号链接,应继续检查链接最终指向的真实文件及其挂载点。若没有 noexec,就不要为了这个猜测改挂载设置;回到当前执行身份、父目录的搜索权限和解释器可访问性等条件。
容器内失败时,要查看容器实际看到的路径和挂载选项。宿主机某个目录允许执行,不代表容器中的绑定挂载具有相同选项。没有 findmnt 的精简镜像,可以读取该环境中的 /proc/self/mountinfo 辅助确认;不要用宿主机同名路径的结果替代它。
解释器能读取脚本,不代表直接执行已恢复
直接执行 ./job.sh,与启动一个解释器并让它读取 job.sh,走的是不同路径。后一种方式执行的是解释器程序,脚本作为输入文件被读取,所以可能出现“直接运行失败,解释器读取成功”的组合。
只有确认脚本可信、运行后果可接受,且其语法符合 POSIX shell 时,才适合这样调用:
sh /srv/jobs/job.sh
这不是纯读取诊断:脚本里的命令会真正执行。包含 Bash 专用语法的脚本不能随意改用 sh,应使用它所要求的解释器。不要把尝试解释器调用当作运行陌生下载脚本的理由。
这种调用也不会修改挂载选项。如果脚本随后直接运行同一 noexec 挂载上的另一个程序,那个程序仍可能被拒绝。因此,解释器调用适合明确允许的脚本工作流,不能作为任意二进制程序的通用修复,也不能据此宣称整套安装程序已恢复。
长期任务优先放到允许执行的位置
如果原目录用于上传、共享数据或临时文件,noexec 可能是既定限制。对于确实需要直接执行的受信任任务,通常更适合把程序部署到允许执行、写入权限受控的目录,数据仍留在原目录。
迁移前先查看目标目录的挂载状态,例如:
findmnt --target /opt --output TARGET,SOURCE,FSTYPE,OPTIONS
/opt 只是候选位置,不保证所有系统都允许执行,也不表示当前用户有权写入。应按现有部署流程创建专用目录,避免覆盖已有程序。保留脚本需要的解释器、相对文件布局、配置和运行身份,然后同步调整定时任务、服务配置或调用方的绝对路径。
不要只复制一个入口文件就删除原目录。脚本可能依赖旁边的配置,也可能按当前工作目录寻找文件。迁移后应使用正式运行身份和正式入口核验,确认没有依赖路径变化,再清理旧副本。
需要调整挂载策略时,先确定配置来源
只有管理员确认这个挂载点本来就应该允许执行,才考虑调整策略。当前生效选项、/etc/fstab、容器挂载配置可能并不一致;修改一处不等于另一处也已改变。
尤其不要直接套用“把整个 /home 或 /tmp 重新挂载为可执行”的命令。它会影响该挂载点上的其他文件,范围远大于一个脚本。绑定挂载与普通挂载的重挂载行为也有区别,应依据实际挂载类型处理,并保留其他安全选项。
调整前保存原挂载信息及对应配置,确认使用该挂载点的服务、恢复方法与维护窗口。调整后重新查看故障发生环境中的实际选项;需要持久化时,还应核对重新挂载或重启后的结果,不能只看配置文件里的文字。
用原入口验证
验收应采用正式任务的启动方式。如果计划继续直接执行脚本,就应在正确目录、正确身份下验证原入口,确认没有再出现权限拒绝,并检查任务的退出状态与预期输出。仅仅看到 sh job.sh 可以运行,不能证明直接执行路径已经修好。
迁移方案失败时,可把调用方路径恢复到此前配置并保留新目录供检查;挂载策略调整需要恢复先前选项及持久配置,再确认实际生效状态。无论选择哪种方案,脚本已经写入的数据或产生的外部操作都不会随配置回退自动撤销,仍需按任务本身的恢复方案处理。


