使用Paramiko exec_command远程执行Python脚本失败问题排查
在远程Ubuntu节点部署了Python脚本read_sensors.py,SSH交互式会话中可全局调用,该脚本用于读取各类指标并写入文本文件,且无法修改其运行逻辑。因同步需求,需从Windows 10端通过SSH远程触发执行该脚本,不能采用cron等定时任务方案。尝试fabric后改用paramiko库:使用invoke_shell方法可成功触发脚本,但使用exec_command方法时,会出现bash: read_sensors.py: command not found错误。由于需要利用stderr做错误处理,需排查该问题的原因及解决方向。
相关代码示例
使用invoke_shell的完整代码
import paramiko import time hostname = "192.168.1.10" username = "user" password = "pw" commands = [ "mkdir 20230212", "read_sensors.py" ] # 初始化SSH客户端 client = paramiko.SSHClient() # 添加到已知主机 client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.connect(hostname=hostname, username=username, password=password) except: print("[!] 无法连接到SSH服务器") exit() remote_conn = client.invoke_shell() # 执行命令 for command in commands: print("="*50, command, "="*50) remote_conn.send(command+' \n') time.sleep(2) output = remote_conn.recv(1000) print(output)
使用exec_command的代码片段
for command in commands: print("="*50, command, "="*50) stdin, stdout, stderr = client.exec_command(command) print(stdout.read().decode()) err = stderr.read().decode() if err: print(err)
对比交互式与非交互式shell的PATH差异:
invoke_shell启动的是交互式shell,会加载用户的shell配置文件(如~/.bashrc、~/.profile),而exec_command默认使用非交互式非登录shell,不会加载这些配置,导致环境变量PATH中没有包含read_sensors.py所在的目录。可通过在exec_command中执行echo $PATH,将输出结果与SSH交互式会话中执行同一命令的结果对比,确认PATH差异。使用脚本绝对路径执行:直接用
read_sensors.py的绝对路径替代命令中的文件名,比如/home/user/scripts/read_sensors.py,绕开PATH环境变量的限制。强制加载shell配置文件:在
exec_command中通过bash参数强制加载配置文件,比如使用登录shell模式:bash -l -c "read_sensors.py",或交互式shell模式:bash -i -c "read_sensors.py",确保配置文件中的PATH设置被加载。验证脚本权限与shebang:确认
read_sensors.py拥有可执行权限(执行chmod +x read_sensors.py),且脚本开头有正确的shebang声明(比如#!/usr/bin/env python3),避免因权限或解释器路径问题导致无法执行。
内容的提问来源于stack exchange,提问作者CanadaRunner

