python3 远程Linux服务器执行命令和上传下载文件
<h2>一、简介</h2><p> paramiko是一个基于SSH用于连接远程服务器并执行相关操作(SSHClient和SFTPClinet,即一个是远程连接,一个是上传下载服务),使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。</p>
<h2>二、使用</h2>
<p><strong>1、下载</strong></p>
<div class="cnblogs_code">
<pre>pip3 install paramiko</pre>
</div>
<p><strong>2、模块使用</strong></p>
<p><strong>SSHClient:</strong></p>
<p> 远程连接分为两种:(1)基于用户名密码连接 (2)基于公钥秘钥连接</p>
<p> 通过是用paramiko远程操作,其实本质也分为两种:(1)只用SSHClient (2)自己创建一个transport</p>
<p>(1)基于用户名和密码的连接</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> paramiko
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 创建SSH对象</span>
ssh =<span style="color: rgba(0, 0, 0, 1)"> paramiko.SSHClient()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 允许连接不在know_hosts文件中的主机</span>
<span style="color: rgba(0, 0, 0, 1)">ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 连接服务器</span>
ssh.connect(hostname=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">c1.salt.com</span><span style="color: rgba(128, 0, 0, 1)">'</span>, port=22, username=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">GSuser</span><span style="color: rgba(128, 0, 0, 1)">'</span>, password=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">123</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 执行命令</span>
stdin, stdout, stderr = ssh.exec_command(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">ls</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 获取命令结果</span>
result =<span style="color: rgba(0, 0, 0, 1)"> stdout.read()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 关闭连接</span>
ssh.close()</pre>
</div>
<p> SSHClient 封装 Transport</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> paramiko
transport </span>= paramiko.Transport((<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">hostname</span><span style="color: rgba(128, 0, 0, 1)">'</span>, 22<span style="color: rgba(0, 0, 0, 1)">))
transport.connect(username</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">GSuser</span><span style="color: rgba(128, 0, 0, 1)">'</span>, password=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">123</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
ssh </span>=<span style="color: rgba(0, 0, 0, 1)"> paramiko.SSHClient()
ssh._transport </span>=<span style="color: rgba(0, 0, 0, 1)"> transport
stdin, stdout, stderr </span>= ssh.exec_command(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">df</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(stdout.read())
transport.close()</span></pre>
</div>
<p>(2)基于公钥秘钥连接</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> paramiko
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 添加公钥密钥文件</span>
private_key = paramiko.RSAKey.from_private_key_file(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/home/auto/.ssh/id_rsa</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 创建SSH对象</span>
ssh =<span style="color: rgba(0, 0, 0, 1)"> paramiko.SSHClient()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 允许连接不在know_hosts文件中的主机</span>
<span style="color: rgba(0, 0, 0, 1)">ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 连接服务器</span>
ssh.connect(hostname=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">192.168.1.105</span><span style="color: rgba(128, 0, 0, 1)">'</span>, port=22, username=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">666</span><span style="color: rgba(128, 0, 0, 1)">'</span>, key=<span style="color: rgba(0, 0, 0, 1)">private_key)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 执行命令</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 执行多条命令时需要将各个命令用‘;’隔开,最后将get_pty设为True;如果是单条命令的则只传入命令即可</span>
stdin, stdout, stderr = ssh.exec_command(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">cd dw/2020-06-02/;ls</span><span style="color: rgba(128, 0, 0, 1)">'</span>,get_pty=<span style="color: rgba(0, 0, 0, 1)">True)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 多条命令的话会将执行结果一起返回,所以建议遍历打印。也可以直接打印:print(stdout.read().decode('utf-8'))</span>
files =<span style="color: rgba(0, 0, 0, 1)"> stdout.readlines()
</span><span style="color: rgba(0, 0, 255, 1)">for</span> i <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> files:
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 打印执行反馈结果</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(i.encode().decode(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">utf-8</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">).split())
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 打印报错信息</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(stderr.read().decode(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">utf-8</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">))
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 关闭连接</span>
ssh.close()</pre>
</div>
<p><strong> SSHClient 封装Transport</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> paramiko
private_key </span>= paramiko.RSAKey.from_private_key_file(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/home/auto/.ssh/id_rsa</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
transport </span>= paramiko.Transport((<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">192.168.1.105</span><span style="color: rgba(128, 0, 0, 1)">'</span>, 22<span style="color: rgba(0, 0, 0, 1)">))
transport.connect(username</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">666</span><span style="color: rgba(128, 0, 0, 1)">'</span>, pkey=<span style="color: rgba(0, 0, 0, 1)">private_key)
ssh </span>=<span style="color: rgba(0, 0, 0, 1)"> paramiko.SSHClient()
ssh._transport </span>=<span style="color: rgba(0, 0, 0, 1)"> transport
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 执行多条命令时需要将各个命令用‘;’隔开,最后将get_pty设为True;如果是单条命令的则只传入命令即可</span>
stdin, stdout, stderr = ssh.exec_command(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">cd dw/2020-06-02/;ls</span><span style="color: rgba(128, 0, 0, 1)">'</span>,get_pty=<span style="color: rgba(0, 0, 0, 1)">True)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 多条命令的话会将执行结果一起返回,所以建议遍历打印。也可以直接打印:print(stdout.read().decode('utf-8'))</span>
files =<span style="color: rgba(0, 0, 0, 1)"> stdout.readlines()
</span><span style="color: rgba(0, 0, 255, 1)">for</span> i <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> files:
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 打印执行反馈结果</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(i.encode().decode(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">utf-8</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">).split())
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 打印报错信息</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(stderr.read().decode(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">utf-8</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">))
transport.close()</span></pre>
</div>
<p><strong>SFTPClient:</strong></p>
<p> 用于连接远程服务器并进行上传下载功能。</p>
<p>(1)基于用户名密码上传下载</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> paramiko
transport </span>= paramiko.Transport((<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">192.168.1.105</span><span style="color: rgba(128, 0, 0, 1)">'</span>,22<span style="color: rgba(0, 0, 0, 1)">))
transport.connect(username</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">666</span><span style="color: rgba(128, 0, 0, 1)">'</span>,password=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">123</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
sftp </span>=<span style="color: rgba(0, 0, 0, 1)"> paramiko.SFTPClient.from_transport(transport)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将location.py 上传至服务器 /tmp/test.py</span>
sftp.put(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/tmp/location.py</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/tmp/test.py</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将remove_path 下载到本地 local_path</span>
sftp.get(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">remove_path</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">local_path</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
transport.close()</span></pre>
</div>
<p>(2)基于公钥秘钥上传下载</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> paramiko
private_key </span>= paramiko.RSAKey.from_private_key_file(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/home/auto/.ssh/id_rsa</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
transport </span>= paramiko.Transport((<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">192.168.1.105</span><span style="color: rgba(128, 0, 0, 1)">'</span>, 22<span style="color: rgba(0, 0, 0, 1)">))
transport.connect(username</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">666</span><span style="color: rgba(128, 0, 0, 1)">'</span>, pkey=<span style="color: rgba(0, 0, 0, 1)">private_key )
sftp </span>=<span style="color: rgba(0, 0, 0, 1)"> paramiko.SFTPClient.from_transport(transport)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将location.py 上传至服务器 /tmp/test.py</span>
sftp.put(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/tmp/location.py</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/tmp/test.py</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将remove_path 下载到本地 local_path</span>
sftp.get(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">remove_path</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">local_path</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
transport.close()</span></pre>
</div>
<p><strong>Demo: 实现远程命令执行和文件上传</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">!/usr/bin/env python</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> -*- coding:utf-8 -*-</span>
<span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> paramiko
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SSHConnection(object):
</span><span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span>(self, host=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">192.168.12.68</span><span style="color: rgba(128, 0, 0, 1)">'</span>, port=22, username=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">locojoy</span><span style="color: rgba(128, 0, 0, 1)">'</span>,pwd=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">123321QQ!</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">):
self.host </span>=<span style="color: rgba(0, 0, 0, 1)"> host
self.port </span>=<span style="color: rgba(0, 0, 0, 1)"> port
self.username </span>=<span style="color: rgba(0, 0, 0, 1)"> username
self.pwd </span>=<span style="color: rgba(0, 0, 0, 1)"> pwd
self.</span><span style="color: rgba(128, 0, 128, 1)">__k</span> =<span style="color: rgba(0, 0, 0, 1)"> None
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> run(self):
self.connect()</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 连接远程服务器</span>
self.upload(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">db.py</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/tmp/1.py</span><span style="color: rgba(128, 0, 0, 1)">'</span>)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 将本地的db.py文件上传到远端服务器的/tmp/目录下并改名为1.py</span>
self.cmd(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">df</span><span style="color: rgba(128, 0, 0, 1)">'</span>)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 执行df 命令</span>
self.close() <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 关闭连接</span>
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> connect(self):
transport </span>=<span style="color: rgba(0, 0, 0, 1)"> paramiko.Transport((self.host, self.port))
transport.connect(username</span>=self.username, password=<span style="color: rgba(0, 0, 0, 1)">self.pwd)
self.</span><span style="color: rgba(128, 0, 128, 1)">__transport</span> =<span style="color: rgba(0, 0, 0, 1)"> transport
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> close(self):
self.</span><span style="color: rgba(128, 0, 128, 1)">__transport</span><span style="color: rgba(0, 0, 0, 1)">.close()
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> upload(self,local_path,target_path):
sftp </span>= paramiko.SFTPClient.from_transport(self.<span style="color: rgba(128, 0, 128, 1)">__transport</span><span style="color: rgba(0, 0, 0, 1)">)
sftp.put(local_path,target_path)
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> cmd(self, command):
ssh </span>=<span style="color: rgba(0, 0, 0, 1)"> paramiko.SSHClient()
ssh._transport </span>= self.<span style="color: rgba(128, 0, 128, 1)">__transport</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 执行命令</span>
stdin, stdout, stderr =<span style="color: rgba(0, 0, 0, 1)"> ssh.exec_command(command)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 获取命令结果</span>
result =<span style="color: rgba(0, 0, 0, 1)"> stdout.read()
</span><span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(result)
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> result
obj </span>=<span style="color: rgba(0, 0, 0, 1)"> SSHConnection()
obj.run()</span></pre>
</div>
<p><strong>paramiko在堡垒机中的应用</strong></p>
<p><strong>(1)简单实例:远程连接一台主机,操作命令,linux版本,输入终端为回车则发送命令。不支持tab补全功能。</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> paramiko, sys, os, socket, select, getpass
</span><span style="color: rgba(0, 0, 255, 1)">from</span> paramiko.py3compat <span style="color: rgba(0, 0, 255, 1)">import</span> u <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 在python3中是这样使用的,如果在Python2中则注释这行</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 这个程序依赖于终端,只能在Liunx下运行,windows用其他的方式</span>
<span style="color: rgba(0, 0, 0, 1)">
tran </span>= paramiko.Transport((<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">192.168.12.68</span><span style="color: rgba(128, 0, 0, 1)">'</span>, 22<span style="color: rgba(0, 0, 0, 1)">,))
tran.start_client()
tran.auth_password(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">locojoy</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">123321QQ!</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 打开一个通道</span>
chan =<span style="color: rgba(0, 0, 0, 1)"> tran.open_session()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 获取一个终端</span>
<span style="color: rgba(0, 0, 0, 1)">chan.get_pty()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 激活器</span>
<span style="color: rgba(0, 0, 0, 1)">chan.invoke_shell()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 原始的方法利用终端进行收发消息</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 利用sys.stdin,肆意妄为执行操作</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 用户在终端输入内容,并将内容发送至远程服务器</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 远程服务器执行命令,并将结果返回</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> 用户终端显示内容</span>
<span style="color: rgba(0, 0, 255, 1)">while</span><span style="color: rgba(0, 0, 0, 1)"> True:
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 监视用户输入和服务器返回数据</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> sys.stdin 处理用户输入</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> chan 是之前创建的通道,用于接收服务器返回信息</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 通过select监听终端(输入输出),一旦变化,就将拿到的数据发送给服务器</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 通过监听socket句柄,如果有变化表示服务器要给我发消息</span>
readable, writeable, error = select.select(,[],[],1<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 通过select.select 监听chan(打开的通道(和远程服务器连接的状态)), sys.stdin(输入),一旦变化就写入readable</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 当chan变化时,加入到readable,远程服务器发送内容过来</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> chan <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> readable:
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">:
x </span>= u(chan.recv(1024))<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> Python3用这个</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> x = chan.recv(1024)Python2使用这个</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> len(x) ==<span style="color: rgba(0, 0, 0, 1)"> 0:
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">\r\n*** EOF\r\n</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">
sys.stdout.write(x) </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 写入缓冲区</span>
sys.stdout.flush() <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 刷新,将缓冲区内容显示出来</span>
<span style="color: rgba(0, 0, 255, 1)">except</span><span style="color: rgba(0, 0, 0, 1)"> socket.timeout:
</span><span style="color: rgba(0, 0, 255, 1)">pass</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 当sys.stdin 放入readable中时,将获取到的内容发送到远程服务器</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> sys.stdin <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> readable:
inp </span>=<span style="color: rgba(0, 0, 0, 1)"> sys.stdin.readline()
chan.sendall(inp)
chan.close()
tran.close()</span></pre>
</div>
<p><strong>(2)每按一个键就发送记录,并支持tab自动补全</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> paramiko, sys, os, socket, select, getpass, termios, tty
</span><span style="color: rgba(0, 0, 255, 1)">from</span> paramiko.py3compat <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> u
tran </span>= paramiko.Transport((<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">10.211.55.4</span><span style="color: rgba(128, 0, 0, 1)">'</span>, 22<span style="color: rgba(0, 0, 0, 1)">,))
tran.start_client()
tran.auth_password(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">wupeiqi</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">123</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 打开一个通道</span>
chan =<span style="color: rgba(0, 0, 0, 1)"> tran.open_session()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 获取一个终端</span>
<span style="color: rgba(0, 0, 0, 1)">chan.get_pty()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 激活器</span>
<span style="color: rgba(0, 0, 0, 1)">chan.invoke_shell()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 获取原tty属性</span>
oldtty =<span style="color: rgba(0, 0, 0, 1)"> termios.tcgetattr(sys.stdin)
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 为tty设置新属性</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 默认当前tty设备属性:</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 输入一行回车,执行</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> CTRL+C 进程退出,遇到特殊字符,特殊处理。</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 这是为原始模式,不认识所有特殊符号</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器</span>
tty.setraw(sys.stdin.fileno())<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 恢复终端原始状态,每按一个键就发送</span>
chan.settimeout(0.0<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">while</span><span style="color: rgba(0, 0, 0, 1)"> True:
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 监视 用户输入 和 远程服务器返回数据(socket)</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 阻塞,直到句柄可读</span>
r, w, e = select.select(, [], [], 1<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> chan <span style="color: rgba(0, 0, 255, 1)">in</span> r:<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 获取服务返回的内容</span>
<span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">:
x </span>= u(chan.recv(1024<span style="color: rgba(0, 0, 0, 1)">))
</span><span style="color: rgba(0, 0, 255, 1)">if</span> len(x) ==<span style="color: rgba(0, 0, 0, 1)"> 0:
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">\r\n*** EOF\r\n</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">
sys.stdout.write(x)
sys.stdout.flush()
</span><span style="color: rgba(0, 0, 255, 1)">except</span><span style="color: rgba(0, 0, 0, 1)"> socket.timeout:
</span><span style="color: rgba(0, 0, 255, 1)">pass</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> sys.stdin <span style="color: rgba(0, 0, 255, 1)">in</span> r: <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 发送命令</span>
x = sys.stdin.read(1) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 读取一个字符</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> len(x) ==<span style="color: rgba(0, 0, 0, 1)"> 0:
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">
chan.send(x) </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 发送一个字符</span>
<span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 重新设置终端属性,将终端状态还原</span>
<span style="color: rgba(0, 0, 0, 1)"> termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
chan.close()
tran.close()</span></pre>
</div>
<p> </p><br><br>
来源:https://www.cnblogs.com/xshan/p/13037604.html
頁:
[1]