python 借助 paramiko 库执行 SSH命令报错:input is not a terminal 解决方式

问题背景

在一个项目中,需要进入环境后台执行一个SSH命令:container_exec -n asv-con -c "sfd_cluster_cmd.sh e 'touch /sf/etc/update_disable_adeploy_upg_precheck'" (类似进入容器中执行配置修改操作),如果人为进入环境后台执行,是有交互输出的,如下图,但是如果使用 paramiko 封装的SSH client 执行这个命令,就报错提示:execing command in container: input is not a terminal

错误原因

错误解析
  1. 错误内容:
    • execing command in container: 表示试图在一个容器中执行命令。
    • input is not a terminal: 表示输入不是一个终端。
  2. 原因:
    • 这个错误通常出现在试图通过一个非交互式的方式执行一个需要终端输入的命令时,比如某些命令可能需要用户在终端交互中提供输入(如密码、确认等)。
    • 当你使用诸如 docker exec 或其他容器管理工具(如 Kubernetes)来执行命令时,如果你没有在命令中启用终端(TTY),就会出现这个问题。

解决办法:强制分配一个伪终端

Python 的 paramiko 库不支持伪终端,但可以通过 get_pty 来实现这一点。可以在执行命令时请求一个伪终端。这样就能执行一些需要终端的命令。完整代码如下

python 复制代码
# -*- coding: utf-8 -*-
# @Desc    :
import threading
import paramiko


class SSH:
    def __init__(self, host, port, username, password):
        """
        初始化ConnectManager对象, 保存连接参数
        :param host: 主机名或IP
        :param port: 端口号
        :param username: 用户名
        :param password: 密码
        """
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.ssh_client = None
        self.connect()

    def connect(self):
        """
        建立SSH连接
        """
        self.ssh_client = paramiko.SSHClient()
        self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            self.ssh_client.connect(self.host, port=self.port, username=self.username, password=self.password)
            print("连接成功{}:{}".format(self.host, self.port))
        except Exception as e:
            print("连接失败:{}".format(e))
            exit(1)

    def close_connection(self):
        """
        关闭SSH连接
        """
        if self.ssh_client:
            self.ssh_client.close()
            print("已关闭连接{}:{}".format(self.host, self.port))

    def execute_command(self, command):
        """
        用于执行命令
        :param command: 执行的命令
        :return: 命令的输出结果
        """
        if not self.ssh_client:
            # SSH连接未建立, 先调用connect建立连接
            self.connect()
    
        # 接收返回值: get_pty: 请求一个伪终端
        stdin, stdout, stderr = self.ssh_client.exec_command(command, get_pty=True)
        
        # 如果需要输入(例如,密码或确认),可以写入 stdin
        # stdin.write('your_input_here\n')
        # stdin.flush()  # 确保输入被发送
    
        if stdout.channel.recv_exit_status() == 0:
            # 返回命令执行结果
            return stdout.read().decode('utf-8').strip(), True
        else:
            # 返回错误信息
            return stderr.read().decode('utf-8').strip(), False
  

相关推荐
白杨尚青9 分钟前
C++入门篇(十):string(上)——认识string:构造与三大遍历(一条龙讲透operator[]、迭代器、auto、范围for)
java·开发语言·c++·笔记·stl
可乐鸡翅yeah_14 分钟前
hls.js 切换多个视频源,新手开发常见踩坑
开发语言·前端·javascript·ios·ffmpeg·音视频·safari
Tanshu_API君17 分钟前
API 聚合平台选型指南:从参数拆解到生产落地的十个评估维度
开发语言·api
Chen—LSN18 分钟前
C语言——⽂件操作(1)
c语言·开发语言·c++·经验分享·笔记·算法·链表
狗凯之家源码网21 分钟前
PHP 开源 IM 即时通讯系统效果实测与功能展示
开发语言·开源·php
虎虎(_ _)。゜zzZ35 分钟前
关于字典中的解包问题
python
辛苦才能38 分钟前
C++ map/set 深度解析:从关联式容器的本质到 operator[] 的三重身份
开发语言·c++
全栈弄潮儿²⁰²⁴40 分钟前
Python实战第2期: 变量与数据类型
python·变量·数据类型·python实战
Chen—LSN1 小时前
C语言——文件操作(2)
c语言·开发语言·c++·经验分享·笔记·算法·c#
纪念 2291 小时前
C++类和对象(最终篇)
开发语言·c++