Python使用paramiko执行远程bash脚本报permission denied错误
问题根因
核心是paramiko通过exec_command执行命令的会话环境,和手动SSH登录、手动开CMD执行的环境完全不一致,和脚本本身的基础执行权限无关,常见触发点有三个:
- 非交互式会话不加载登录环境配置:手动SSH登录是交互式登录shell,会自动加载
/etc/profile、用户目录下.bashrc/.bash_profile里的所有配置,包括SVN命令路径、仓库访问权限、sudo免密规则;但exec_command默认启动的是非登录非交互式shell,不会加载上述配置,执行SVN相关操作时要么找不到命令,要么没有仓库目录的访问权限,直接抛权限拒绝。 - 缺少伪终端触发权限拦截:如果脚本里有提权操作,远程sshd默认要求sudo等操作必须在tty终端下执行,非交互会话没有tty会直接被权限规则拦截。
- 权限链路不匹配:一是脚本执行时umask默认值和手动登录时不一致,写入
/data/audit的生成文件权限过严,后续SCP拉取时读不到;二是Python进程在Windows侧的运行权限和你手动开CMD的权限不一致,如果本地保存路径是C盘根目录、Program Files这类受UAC管控的目录,Python进程没有本地写入权限也会报permission denied,很容易被误判为远程侧的问题。
可直接落地的修复方案
- 调整paramiko的命令执行逻辑,强制加载登录环境+分配伪终端:
# 替换原有直接传入脚本内容的exec_command调用 stdin, stdout, stderr = ssh.exec_command( # 用-l参数指定bash为登录shell,加载全量环境配置 f"bash -l -c '{script_content}'", # 分配伪终端,绕过tty权限校验 get_pty=True ) # 打印错误输出定位具体报错点 err_msg = stderr.read().decode('utf-8') if err_msg: print(f"远程脚本执行报错: {err_msg}") exit_code = stdout.channel.recv_exit_status() print(f"远程脚本执行退出码: {exit_code}")
- 校准文件权限:在bash脚本写入采集结果到
/data/audit后,显式加一行权限配置,避免umask差异导致文件不可读:
# 脚本里写完结果文件后追加 chmod 644 /data/audit/匹配你采集结果文件名的规则
- 排查本地侧权限问题:把SCP拉取的本地保存路径改成当前用户目录下的非管控路径(比如桌面自建的工作目录),不要存在需要管理员权限才能写入的系统目录;如果必须存系统目录,启动Python脚本时右键选择「以管理员身份运行」。
- 如果脚本内用到sudo提权操作,需要在远程服务器sudoers配置中,给SSH连接使用的用户添加对应操作的NOPASSWD权限,同时关闭该用户的tty校验要求。
内容的提问来源于stack exchange,提问作者Champs
相关产品推荐
相关产品推荐

