Ansible 执行脚本提示 Permission denied 即使使用了 become,主要原因是脚本文件缺少执行权限,或者使用的模块(如 synchronize)在本地运行不受 become 控制。become 仅解决用户身份提权,不自动修正文件权限位。
先说结论:become 负责身份切换,不负责文件 chmod,需单独处理脚本权限和模块上下文。
- 先确认:脚本文件是否拥有执行权限位(x)。
- 先处理:在任务中显式声明 become: yes 并确保 sudo 配置正确。
- 再验证:使用 -vvv 参数查看权限提升是否实际生效。
命令速用版
若脚本位于受控主机,先修复文件权限:
chmod +x /path/to/script.sh
若需提权执行,Ansible 命令添加 become 标志:
ansible-playbook site.yml `--become` `--become-user`=root
若使用 synchronize 模块报错,指定 rsync 路径:
rsync_path: /usr/bin/rsync
为什么会这样
become 机制仅改变执行任务的用户身份,不改变文件本身的 POSIX 权限位。Linux 内核在执行脚本时,若文件缺少执行位(x),即使 root 用户也会因安全策略拒绝 execve 调用。此外,部分模块如 synchronize 工作在控制节点本地,不受受控主机 become 配置影响,导致权限上下文错位。
分步处理
第一步:检查脚本文件权限。登录受控主机执行 ls -l script.sh,若显示 -rw-r`--r--` 则缺少执行位。运行 chmod +x script.sh 赋予执行权限。
第二步:确认 Playbook 提权配置。在 task 级别添加 become: yes,确保成为目标用户。若默认用户无 sudo 权限,需配置 ansible_become_pass 或 SSH 密钥。
第三步:排查特殊模块限制。若使用 synchronize 模块,注意其运行在本地主机,需在模块参数中指定 rsync_path,或预先调整远程目录所有权。
怎么验证是否生效
执行 ansible-playbook 时添加 -vvv 参数,观察输出中是否包含 Becoming user root 或类似提权日志。检查受控主机目标文件的属主和权限位是否符合预期。若使用 script 模块,查看返回的 rc 代码是否为 0。
常见坑
文件系统挂载了 noexec 选项,即使 chmod 777 也无法执行脚本,需 mount 命令检查挂载点标志。synchronize 模块忽略 become 字段,误以为已提权操作远程 root 目录,实际仍为本地普通用户权限。临时目录/tmp 在某些发行版默认配置 noexec,避免将脚本放在此处执行。
常见问题
为什么加了 become 还是 Permission denied?
因为文件本身缺少执行权限位,become 只提升用户身份不修改文件属性。
synchronize 模块报错 permission denied 怎么办?
该模块在本地运行不受 become 影响,需指定 rsync_path 或调整远程目录权限。
如何确认 become 是否真正生效?
使用 ansible-playbook -vvv 查看调试日志,确认是否有提权操作记录。
参考来源
- Ansible 重启 Tomcat 时提示'Permission denied'执行 systemd-sysv-install,根本原因和实操解法有哪些?
- Linux 下执行脚本时提示“Permission denied”如何解决?
- Ansible 的 Synchronize 模块报错总结 (code 12, Permission denied, Operation not permitted)
- ansible 学习系列之 become 的使用