问题背景
在一个项目中,需要进入环境后台执行一个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

错误原因
错误解析
- 错误内容:
- execing command in container: 表示试图在一个容器中执行命令。
- input is not a terminal: 表示输入不是一个终端。
- 原因:
- 这个错误通常出现在试图通过一个非交互式的方式执行一个需要终端输入的命令时,比如某些命令可能需要用户在终端交互中提供输入(如密码、确认等)。
- 当你使用诸如 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