paramiko

该模块基于SSH用于连接远程服务器并执行相关操作

SSHClient

远程连接服务器有两种方法:SSHClient、tranceport

用于连接远程服务器并执行基本命令

基于用户名密码连接:

 1 import paramiko
 2 # 创建SSH对象
 3 ssh = paramiko.SSHClient()
 4 # 允许连接不在know_hosts文件中的主机
 5 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
 6 # 连接服务器
 7 ssh.connect(hostname='192.168.247.131', port=22, username='root', password='111111')
 8 # 执行命令
 9 stdin, stdout, stderr = ssh.exec_command('pwd')
10 # 获取命令结果
11 result = stdout.read()
12 print(result)
13 # 关闭连接
14 ssh.close() 

SSHClient封装transport

 1 import paramiko
 2 
 3 transport = paramiko.Transport(('hostname', 22))
 4 transport.connect(username='wupeiqi', password='123')
 5 
 6 ssh = paramiko.SSHClient()
 7 ssh._transport = transport
 8 
 9 stdin, stdout, stderr = ssh.exec_command('df')
10 print stdout.read()
11 
12 transport.close()

基于公钥密钥连接:

 1 import paramiko
 2 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
 3 # 创建SSH对象
 4 ssh = paramiko.SSHClient()
 5 # 允许连接不在know_hosts文件中的主机
 6 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
 7 # 连接服务器
 8 ssh.connect(hostname='192.168.247.131', port=22, username='root', key=private_key)
 9 # 执行命令
10 stdin, stdout, stderr = ssh.exec_command('df')
11 # 获取命令结果
12 result = stdout.read()
13 
14 
15 
16 # 关闭连接
17 
18 ssh.close()

封装

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', pkey=private_key)

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')

transport.close()

SFTPClient

实现文件下载的方法:Tranceport

用于连接远程服务器并执行上传下载

基于用户名密码上传下载

 1 import paramiko
 2 
 3  
 4 
 5 transport = paramiko.Transport(('hostname',22))
 6 
 7 transport.connect(username='wupeiqi',password='123')
 8 
 9  
10 
11 sftp = paramiko.SFTPClient.from_transport(transport)
12 
13 # 将location.py 上传至服务器 /tmp/test.py
14 
15 sftp.put('/tmp/location.py', '/tmp/test.py')
16 
17 # 将remove_path 下载到本地 local_path
18 
19 sftp.get('remove_path', 'local_path')
20 
21  
22 
23 transport.close()

基于公钥密钥上传下载

import paramiko

 

private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

 

transport = paramiko.Transport(('hostname', 22))

transport.connect(username='wupeiqi', pkey=private_key )

 

sftp = paramiko.SFTPClient.from_transport(transport)

# 将location.py 上传至服务器 /tmp/test.py

sftp.put('/tmp/location.py', '/tmp/test.py')

# 将remove_path 下载到本地 local_path

sftp.get('remove_path', 'local_path')

 

transport.close()

通过以上分析,可以知道,如果想实现远程连接执行命令,只能使用tranceport方法。

通过利用transport和SSHClient实现在一次链接中多次执行命令和上传、下载文件。

 1 import paramiko
 2 import uuid
 3 class SSHConnection(object):
 4     def __init__(self,host='192.168.247.131',port=22,username='root',pwd='111111'):
 5         self.host = host
 6         self.port = port
 7         self.username = username
 8         self.pwd = pwd
 9         self._k = None
10 
11     def run(self):
12         self.connect()
13         pass
14         self.close()
15 
16     def connect(self):
17         transport = paramiko.Transport((self.host,self.port))
18         transport.connect(username=self.username,password=self.pwd)
19         self.__transport = transport
20     def close(self):
21         self.__transport.close()
22     def cmd(self,command):
23         ssh = paramiko.SSHClient()
24         ssh._transport = self.__transport
25         stdin,stdout,stderr = ssh.exec_command(command)
26         result = stdout.read()
27         return result
28     def upload(self,local_path,target_path):
29         sftp = paramiko.SFTPClient.from_transport(self.__transport)
30         sftp.put(local_path,target_path)
31 
32 def create_file(self):
33     file_name = str(uuid.uuid4())
34     with open(file_name, 'w') as f:
35         f.write('sb')
36     return file_name
37 ssh = SSHConnection()
38 #上传文件、执行命令
39 ssh.connect()
40 r1 = ssh.cmd('df')
41 print(r1)
42 ssh.upload('s2.py','/home/s7.py')
43 ssh.close()

 上面的例子是将命令写入代码中,并返回执行结果,下面我们就来介绍通过终端输入命令,等待返回结果:

1.输入命令点回车,执行命令,等待结果(linux终端默认只有点击回车,io中的stdin才会有变化),不支持tab补全

2.每输入一个字就给服务器传过去,然后再点回车,服务器执行传来的命令。(改变终端的模式)

第一个实例

 

 1 import paramiko
 2 import sys
 3 import os
 4 import socket
 5 import select
 6 import getpass
 7 # from paramiko.py3compat import u   py27需要注释
 8 tran = paramiko.Transport(('192.168.247.128',22,))
 9 tran.start_client()
10 tran.auth_password('root','111111')
11 #打开一个通道
12 chan = tran.open_session()
13 #获取一个通道
14 chan.get_pty()
15 #激活器
16 chan.invoke_shell()
17 while True:
18     #监视用户输入和服务器返回数据
19     #sys.stdin 处理用户输入
20     #chan是之前创建的通道,用于就收服务器返回信息
21     readable,writeable,error = select.select([chan,sys.stdin,],[],[],1)
22     if chan in readable:        #此处的chan是服务器通过执行命令,返回的结果
23         try:
24             #x = u(chan.recv(1024))
25             x = chan.recv(1024)      #py27写法
26             if len(x) == 0:
27                 print('\r\n*** EOF\r\n')
28                 break
29             sys.stdout.write(x)
30             sys.stdout.flush()         #刷新缓冲区,将内容打印到屏幕
31         except socket.timeout:
32             pass
33     if sys.stdin in readable:
34         inp = sys.stdin.readline()
35         chan.sendall(inp)
36 chan.close()
37 tran.close()

 

第二个实例

 1 import paramiko
 2 import sys
 3 import os
 4 import socket
 5 import select
 6 import getpass
 7 import tty
 8 import termios
 9 # from paramiko.py3compat import u   py27需要注释
10 tran = paramiko.Transport(('192.168.247.128',22,))
11 tran.start_client()
12 tran.auth_password('lwq','123')
13 #打开一个通道
14 chan = tran.open_session()
15 #获取一个通道
16 chan.get_pty()
17 #激活器
18 chan.invoke_shell()
19 #获取原tty属性,目的是为了在操作完以后恢复终端原型
20 oldtty = termios.tcgetattr(sys.stdin)
21 try:
22     #为tty设置新属性
23     #默认当前tty设备属性
24     #输入一行回车,执行
25     #ctrl +c 进程退出,遇到特殊字符,特殊处理
26     #这是为原始模式,不认识特殊字符号
27     #放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到 远程服务器
28     tty.setraw(sys.stdin.fileno())
29     chan.settimeout(0.0)
30     while True:
31         #监视用户输入和服务器返回数据
32         #阻塞,直到句柄可读
33         readable,writeable,error = select.select([chan,sys.stdin,],[],[],1)
34         if chan in readable:
35             try:
36                 #x = u(chan.recv(1024))
37                 x = chan.recv(1024)      #py27写法
38                 if len(x) == 0:
39                     print('\r\n*** EOF\r\n')
40                     break
41                 sys.stdout.write(x)
42                 sys.stdout.flush()
43             except socket.timeout:
44                 pass
45         if sys.stdin in readable:
46             inp = sys.stdin.read(1)
47             if len(inp) == 0:
48                 break
49             chan.send(inp)
50 finally:
51     #重新设置终端属性
52     termios.tcsetattr(sys.stdin,termios.TCSADRAIN,oldtty)
53 chan.close()
54 tran.close()