如何用Python模拟分步SSH登录远程Unix服务器并执行命令?
问题描述
- 需自动化跨服务器业务流程:从源服务器获取数据后,在目标Unix服务器运行处理程序
- 手动操作流程:先SSH登录目标服务器,再执行命令,程序可正常运行
- 远程单命令执行(
ssh username@server {command}):程序能启动,但触发Oracle服务器二次报错 - 已尝试三种Python实现方式(
os.system、subprocess、paramiko),均出现相同Oracle报错
问题根源
远程执行单条命令时,SSH默认启动非交互式非登录shell,不会加载用户shell的初始化配置文件(如~/.bashrc、~/.profile)。而手动登录时是交互式登录shell,会加载这些文件,其中包含Oracle运行必需的环境变量(如ORACLE_HOME、PATH、LD_LIBRARY_PATH),环境变量缺失导致程序报错。
解决方案
核心是让远程shell加载初始化配置,模拟手动登录的环境,以下是两种Python实现方式:
方式一:通过subprocess调用登录shell执行命令
在远程命令中指定启动登录式bash,强制加载配置文件:
import subprocess # 构造命令:用bash -l启动登录shell,再执行目标命令 # 注意:如果command包含引号,需要用转义或三重引号包裹 cmd = f'ssh username@server "bash -l -c \'{command}\'"' # 执行命令并捕获输出 result = subprocess.run(cmd, shell=True, capture_output=True, text=True) print("输出内容:", result.stdout) print("错误信息:", result.stderr)
bash -l:启动登录shell,会加载~/.profile等登录相关配置- 若依赖
~/.bashrc,可改用bash -i -c '{command}'启动交互式shell
方式二:用paramiko创建交互式shell会话
使用paramiko的invoke_shell创建交互式会话,完全模拟手动登录后执行命令的流程:
import paramiko import time sshcon = paramiko.SSHClient() sshcon.set_missing_host_key_policy(paramiko.AutoAddPolicy()) sshcon.connect(hostname, username, key_filename=ssh_key_path) # 创建交互式shell shell = sshcon.invoke_shell() time.sleep(1) # 等待shell初始化完成 # 发送命令(末尾加换行符模拟回车) shell.send(f"{command}\n") time.sleep(5) # 根据命令执行时长调整等待时间 # 获取执行输出 output = shell.recv(65535).decode('utf-8') print(output) sshcon.close()
- 这种方式完全还原手动登录的交互环境,会自动加载所有shell初始化文件
- 可通过检测输出中的命令提示符(如
$、#)来动态判断命令是否执行完成,替代固定等待时间
备选方案:手动指定Oracle环境变量
若不想依赖shell配置文件,可在执行目标命令前手动设置Oracle环境变量:
import subprocess # 先设置Oracle环境变量,再执行目标命令 oracle_cmd = f'export ORACLE_HOME=/your/oracle/path; export PATH=$ORACLE_HOME/bin:$PATH; export LD_LIBRARY_PATH=$ORACLE_HOME/lib; {command}' cmd = f'ssh username@server "{oracle_cmd}"' result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
内容的提问来源于stack exchange,提问作者DarknessFalls
相关产品推荐
相关产品推荐

