python paramiko 交互

python交互的模块挺多:pexpect、paramiko 、fabric、

前两个包使用过,但独 paramiko 频率高, 简单丰富,重要的是还多坑!有句老实话不知当不当讲,越骚动的郑就越喜欢,因为征服了它就能征服天下

一 、安装

  • 省略

     #
    

二、 工程测试实例

  • 公用

    class SSHConn(object):
        __ssh = None
        __transport = None
        __LOGIN_SUCCESS__ = False
    
        def __init__(self, host, port, username, password):
            self.__host = host
            self.__port = port
            self.__username = username
            self.__password = password
    
        def login(self):
            """ 登入测试 """
            error_msg = None
            try:
                transport = paramiko.Transport((self.__host, int(self.__port)))
                transport.start_client()
                transport.auth_password(self.__username, self.__password)
                # transport.connect(username=self.__username, password=self.__password)
                if transport.active is True:
                    self.__LOGIN_SUCCESS__ = True
                    ssh = paramiko.SSHClient()
                    ssh._transport = transport
                    self.__ssh = ssh
                    self.__transport = transport
            except Exception:
                error_msg = traceback.format_exc()
                # error_msg = f'{e}'
            finally:
                return self.__LOGIN_SUCCESS__, error_msg
    
        def send_channel(self, cmd, channel):
            cmd = str(cmd) + '\r'
            # 通过命令执行提示符来判断命令是否执行完成
            # p = re.compile(r']$')
            result = ''
            # 发送要执行的命令
            channel.send(cmd)
            count = 1
            # 回显很长的命令可能执行较久,通过循环分批次取回回显
            # root 用户非root用户回显的内容不一样,循环判断逻辑需要修改
            if self.__username == 'root':
                while '~]#' not in result:
                    time.sleep(0.5)
                    count += 1
                    print("count: ", count)
                    ret = channel.recv(65535)
                    ret = ret.decode('utf-8')
                    result += ret
                    # if p.search(ret):
                    if 'Permission denied' in result:
                        break
                    elif 'password for {0}'.format(self.__username) in result:
                        break
                return result
            # 普通用户
            while '~]$' not in result:
                time.sleep(0.5)
                count += 1
                print("count: ", count)
                ret = channel.recv(65535)
                ret = ret.decode('utf-8')
                result += ret
                # if p.search(ret):
                if 'Permission denied' in result:
                    break
                elif 'password for {0}'.format(self.__username) in result:
                    break
            return result
    
        def check_login(self):
            """ 检查登入状态 """
            json_ret, error_msg = self.login()
            if self.__LOGIN_SUCCESS__ is not False:
                return json_ret, error_msg
            return "检查到未登入"
    
        def close(self):
            """ 关闭连接/传输 """
            if self.__LOGIN_SUCCESS__:
                self.__ssh.close()
                self.__transport.close()
            else:
                return "登入失败"
    
  • 调用公用满足业务逻辑

     def run_cmd(self, cmd):
            """ 执行命令 获取系统cmd列表内相关信息接口 """
            json_ret = {"code": 200, "msg": "执行成功", "data": []}
            if type(cmd) is dict:
                inner_dict = dict()
                for k, v in cmd.items():
                    # 打开通道
                    channel = self.__transport.open_session()
                    channel.settimeout(100)
                    # 获取终端
                    channel.get_pty()
                    # 激活
                    channel.invoke_shell()
                    str_res = self.send_channel(v, channel)
                    print('====')
                    print('str_res_ooo1: ', str_res)
                    print('------')
                    # 可能会出现回显的用if判断
                    if 'Permission denied' in str_res:
                        str_res = self.send_channel('sudo {0}'.format(v), channel)
                        print('retttt: ', str_res)
    
                        if 'password for {0}'.format(self.__username) in str_res:
                            str_res = self.send_channel(self.__password, channel)
                            print("str_res11______password: ", str_res)
    
                    elif 'password for {0}'.format(self.__username) in str_res:
                        str_res = self.send_channel(self.__password, channel)
                        print("str_res22______password: ", str_res)
                    # self.close()
                    # print('resp: ', type(resp),  resp)
                    # ret = str(resp, encoding='utf-8', errors='ignore')
                    # 以原始键值对返回数据,暂不做处理
                    print('str_res_00: ', type(str_res), str_res)
                    if str_res and '\n' in str_res:
                        print(1111)
                        print('str_res__11: ', len(str_res), type(str_res), str_res)
                        # json_ret['data'].append({k: str_res})
                        inner_dict[k] = str_res
                    elif not str_res or str_res == '' or str_res == 'null':
                        print(2222)
                        # json_ret['data'].append({k: None})
                        inner_dict[k] = None
                        print('json_ret__222')
                    else:
                        print(3333)
                        json_ret['msg'] = "未知回显数据及类型"
                        inner_dict[k] = 'null'
                json_ret['data'].append(inner_dict)
                return {"code": 200, "msg": "执行成功", "data": {"data": [inner_dict]}}
            elif type(cmd) is list:
                try:
                    for k_v in cmd:
                        for k, v in k_v.items():
                            # 打开通道
                            channel = self.__transport.open_session()
                            channel.settimeout(100)
                            # 获取终端
                            channel.get_pty()
                            # 激活
                            channel.invoke_shell()
                            str_res = self.send_channel(v, channel)
                            print('====')
                            print('str_res_ooo1: ', str_res)
                            print('------')
                            # 可能会出现回显的用if判断
                            if 'Permission denied' in str_res:
                                str_res = self.send_channel('sudo {0}'.format(v), channel)
                                print('retttt: ', str_res)
    
                                if 'password for {0}'.format(self.__username) in str_res:
                                    str_res = self.send_channel(self.__password, channel)
                                    print("str_res11______password: ", str_res)
    
                            elif 'password for {0}'.format(self.__username) in str_res:
                                str_res = self.send_channel(self.__password, channel)
                                print("str_res22______password: ", str_res)
                            # self.close()
                            # print('resp: ', type(resp),  resp)
                            # ret = str(resp, encoding='utf-8', errors='ignore')
                            # 以原始键值对返回数据,暂不做处理
                            print('str_res_00: ', type(str_res), str_res)
                            if str_res and '\n' in str_res:
                                print('str_res__11: ', len(str_res), type(str_res), str_res)
                                json_ret['data'].append({k: str_res})
                            elif not str_res or str_res == '' or str_res == 'null':
                                json_ret['data'].append({k: None})
                                print('json_ret__222')
                            else:
                                json_ret['msg'] = "未知回显数据及类型"
                                json_ret['data'].append({k: 'null'})
                    # return json_ret
                except Exception:
                    # json_ret['msg'] = f"错误原因:{e}"
                    json_ret['msg'] = traceback.format_exc()
                    json_ret['code'] = -1
                finally:
                    return json_ret
            else:
                json_ret['msg'] = "仅支持输入 [{'k':'cmd'}] 格式数据"
            return json_ret
    
  • 业务逻辑可参考

    	def sys_status(self):
            """ 获取获取运行状况 """
            cmd_dict = {"disk_free": "df -k", "mem_free": "free", "ps_aux": "ps -aux", "netstat": "netstat -atunp",
                        "vmstat": "vmstat"}
            json_ret = self.run_cmd(cmd_dict)
            return json_ret
    
        def sys_info(self):
            """ 获取系统 cmd_list 列表内相关信息接口 """
            cmd_list = [{"hostname": 'hostname'}, {'kernel_version': 'uname -r'},
                        {"release_version": "cat /etc/redhat-release"},
                        {"ifconfig": "ifconfig"}, {"etc_passwd": "cat /etc/passwd"}, {"etc_group": "cat /etc/group"},
                        {"etc_login_defs": "cat /etc/login.defs"}, {"etc_pam_system_auth": "cat /etc/pam.d/system-auth"},
                        {"chkconfig_list": "chkconfig --list"}, {"etc_profile": "cat /etc/profile"},
                        {"etc_initab": "cat /etc/initab"}, {"etc_sshd_config": "cat /etc/sshd_config"},
                        {"etc_snmpd_conf": "cat /etc/snmp/snmpd.conf"},
                        {"sensitive_file_permission": "ls -al /etc/passwd"},
                        {"sensitive_file_permission": "ls -al /etc/group"},
                        {"sensitive_file_permission": "ls -al /etc/shadow"},
                        {"cat_shadow": "cat /etc/shadow"},
                        {"log_file_permission": "ls -al /var/log/secure"},
                        {"log_file_permission": "ls -al /var/log/message"},
                        {"log_file_permission": "ls -al /var/log/cron"},
                        {"syslog_conf": "cat /etc/syslog.conf"}, {"syslog_conf": "cat /etc/rsyslog.conf"}]
    
            json_ret = self.run_cmd(cmd_list)
            return json_ret
    
  • 拓展,切换用户需要使用到 ssh.invoke_shell() 打开终端,其他通道方式不行,此下内容来自博友:戳她

    import paramiko
    	import time
    	
    	ssh = paramiko.SSHClient()
    	ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    	try:
    	    ssh.connect(hostname="250.250.250.250", port=80, username="username", password="password")
    	    channel = ssh.invoke_shell()
    	    time.sleep(0.1)
    	    
    	    channel.send("su - \n")
    	    buff = ''
    	    while not buff.endswith('Password: '):
    	        resp = channel.recv(9999)
    	        buff += resp.decode('utf-8')
    	    # print(buff)
    	    
    	    channel.send("Changeme_123")
    	    channel.send('\n')
    	    buff = ''
    	    while not buff.endswith('# '):  # 当指令执行结束后,Linux窗口会显示#,等待下条指令,所以可以用作识别全部输出结束的标志。
    	        resp = channel.recv(9999)
    	        buff += resp.decode('utf-8')
    	    # print(buff)
    	
    	    print("------end------")
    	   
    		# 查看是否切换成功
    		channel.send("whoami")
    		channel.send("\n")
    		buff = ''
    		while not buff.endswith('# '):
    		    resp = channel.recv(9999)
    		    buff += resp.decode('utf-8')
    		print(buff)
    		
    	except paramiko.ssh_exception.AuthenticationException:
    	    print('Failed to login. ip username or password not correct.')
    	    exit(-1)
    
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python Paramiko 是一个用于 SSH 和 SFTP 的 Python 模块,可以实现实时交互。通过 Paramiko,可以在 Python 中远程执行命令、上传和下载文件等操作。在实时交互中,可以通过 Paramiko 的 SSHClient 类的 invoke_shell() 方法来创建一个交互式的 shell。然后,可以使用 send() 方法发送命令,使用 recv() 方法接收命令的输出。同时,还可以使用 select 模块来实现非阻塞式的交互。 ### 回答2: Python paramiko 是一个用于远程登录和管理的模块,常用于远程服务器管理和自动化测试等方面。在使用 paramiko 进行实时交互时,主要有以下几个步骤: 1. 连接远程服务器:首先需要使用 SSHClient() 方法创建一个 SSH 连接,然后使用 .connect() 方法连接远程服务器,参数包括远程服务器地址、端口号、用户名和密码等信息。 2. 执行命令:使用 .exec_command() 方法执行命令,该方法返回三个值,包括标准输入、标准输出和标准错误输出,我们通常会用到标准输出。可以使用 .readlines() 方法获取命令执行的结果,并将结果打印输出。 3. 交互操作:有些命令需要交互操作,例如输入密码等。此时需要创建一个 Channel 对象,并使用 .invoke_shell() 方法打开一个交互终端。然后使用 .send() 方法发送需要操作的命令或数据,使用 .recv() 方法接收命令执行的返回结果。需要注意的是,每次接收到返回结果后,都需要使用 .recv_ready() 方法判断是否还有数据,如果没有数据则交互结束。 下面给出一个简单的代码示例,该示例用于实现在远程服务器上安装 nginx 并启动服务的过程。 ``` import paramiko # 创建 SSHClient 对象 ssh = paramiko.SSHClient() # 自动保存远程主机的 SSH 公钥 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接远程服务器 ssh.connect('xxx.xxx.xxx.xxx', port=22, username='root', password='123456') # 安装 nginx stdin, stdout, stderr = ssh.exec_command('yum install -y nginx') print(stdout.readlines()) print(stderr.readlines()) # 启动 nginx 服务 channel = ssh.invoke_shell() channel.send('systemctl start nginx\n') while True: if channel.recv_ready(): print(channel.recv(1024).decode()) break # 关闭连接 ssh.close() ``` 在上述代码中,首先通过调用 .exec_command() 方法安装 nginx,然后通过调用 .invoke_shell() 方法打开交互终端,在终端中发送启动 nginx 服务的命令,并循环接收返回结果。最后关闭连接,本次实时交互结束。 ### 回答3: Python ParamikoPython编程语言的SSH客户端。通过Paramiko库,我们可以实现与远程计算机的SSH交互,包括执行Shell命令、传输文件、端口转发等操作。本文将介绍如何使用Paramiko实现Python与远程计算机之间的实时交互Paramiko库提供了SSHClient类,它实现了与SSH服务器之间的远程交互。要创建SSHClient对象,我们可以执行以下代码: ``` import paramiko ssh = paramiko.SSHClient() ``` 然后,要连接到远程计算机,需要使用SSHClient对象的connect()方法,例如: ``` ssh.connect(hostname='remote_host', port=22, username='username', password='password') ``` 连接成功后,我们就可以执行远程Shell命令,例如: ``` stdin, stdout, stderr = ssh.exec_command('ls -l') print(stdout.read()) ``` 上述代码执行了一条ls -l命令,以列表形式返回了目标目录下的文件和目录的详细列表。 如果我们需要与执行命令的交互,我们需要调用SSHClient对象的invoke_shell()方法,例如: ``` channel = ssh.invoke_shell() ``` 然后,我们就可以使用channel对象的方法执行实时交互。例如,如果我们需要在远程计算机上启动一个Python解释器,并执行Python代码: ``` channel.send('python\n') channel.send('print("Hello, world!")\n') response = channel.recv(1024) print(response.decode()) ``` 上述代码从本地电脑向远程计算机发送两个命令。第一个命令是打开Python解释器,第二个命令是使用解释器运行一行代码,打印出“Hello,world!” 最后,我们需要断开连接,我们可以使用SSHClient对象的close()方法: ``` ssh.close() ``` 总之,Python Paramiko库提供了强大的实现Python与远程计算机之间实时交互的能力。通过它,我们可以轻松地实现远程Shell命令和Python交互

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值