Python的paramiko模块,该模块基于SSH用于连接远程服务器并执行相关操作。
SSHClient
用于连接远程服务器并执行基本命令
基于用户名密码连接:
方法1:
import paramiko # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname='c1.salt.com', port=22, username='root', password='123') # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() # 关闭连接 ssh.close()
方法2:
使用transport封装来实现
import paramiko # 封装transport 获取到主机、端口、用户名、密码 transport = paramiko.Transport(('192.168.56.11', 22)) transport.connect(username='root', password='123') # 基于transport来连接 ssh = paramiko.SSHClient() ssh._transport = transport # 执行命令,标准输入、输出、错误 stdin, stdout, stderr = ssh.exec_command('df') print stdout.read() transport.close()
基于密钥的连接
方法1:
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 ssh.connect(hostname='c1.salt.com', port=22, username='root', key=private_key) # 执行命令 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() # 关闭连接 ssh.close()
方式二:
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') transport = paramiko.Transport(('192.168.56.12', 22)) transport.connect(username='root', pkey=private_key) ssh = paramiko.SSHClient() ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('df') transport.close()
SFTPClient
用于连接远程服务器并执行上传下载
基于用户名密码上传下载
import paramiko
transport = paramiko.Transport(('192.168.56.12',22))
transport.connect(username='root',password='123')
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()
基于公钥密钥上传下载
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
# 封装transport对象
transport = paramiko.Transport(('192.168.56.12', 22))
transport.connect(username='root', 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()
使用paramiko使用简单的上传下载
方式一:
连接方式选择不实用transport的方式
#!/usr/bin/env python
# coding:utf-8
import paramiko
import uuid
class haproxy(object):
# 初始化
def __init__(self):
self.host = '192.168.56.11'
self.port = 22
self.username = 'root'
self.pwd = '123456'
# 创建文件,使用UUID来生成名字,一个字符串
def creat_file(self):
file_name = str(uuid.uuid4())
with open(file_name,'w') as f:
f.write('sbsbsbsbsb')
# 将文件名封装到内存中
return file_name
def run(self):
self.upload()
self.rename()
# 上传文件
def upload(self):
# 在本地创建文件,名称是file_name
file_name = self.creat_file()
transport = paramiko.Transport((self.host, self.port))
transport.connect(username=self.username, password=self.pwd)
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put(file_name, '/home/root/dddddddddddddd.py')
transport.close()
# 文件重命名
def rename(self):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=self.host, port=self.port, username=self.username, password=self.pwd)
stdin,stdout,stderr = ssh.exec_command('mv /home/root/dddddddddddddd.py /home/root/ssssssssssss.py')
result = stdout.read()
ssh.close()
a = haproxy()
a.run()
方法2:
使用transport连接方式
#!/usr/bin/env python
# coding:utf-8
import paramiko
import uuid
class haproxy(object):
def __init__(self):
self.host = '192.168.56.12'
self.port = 22
self.username = 'root'
self.pwd = '123456'
def creat_file(self):
file_name = str(uuid.uuid4())
with open(file_name,'w') as f:
f.write('sbsbsbsbsb')
return file_name
def run(self):
self.connect()
self.upload()
self.rename()
self.close()
def connect(self):
transport = paramiko.Transport((self.host, self.port))
transport.connect(username=self.username, password=self.pwd)
self.__transport = transport
def close(self):
self.__transport.close()
def upload(self):
self.__transport = self.__transport
file_name = self.creat_file()
sftp = paramiko.SFTPClient.from_transport(self.__transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put(file_name, '/ssssssssssss.py')
def rename(self):
ssh = paramiko.SSHClient()
self.__transport = self.__transport
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=self.host, port=self.port, username=self.username, password=self.pwd)
stdin,stdout,stderr = ssh.exec_command('mv /ssssssssssss.py /dddddddddddddd.py')
result = stdout.read()
a = haproxy()
a.run()
之前上面的两种实现方式都不能实现持续连接服务器,下面咱们来搞搞让他更持久。。。。。
持久一:
他会直接连接到远程服务器上
#!/usr/bin/env python
# coding:utf-8
import sys
import select
import socket
import paramiko
# 使用transport封装一个tran,
tran = paramiko.Transport(('192.168.56.12',22))
tran.start_client()
# 使用用户名密码的方式连接
tran.auth_password('root','123456')
# 打开一个通道
chan = tran.open_session()
# 获取一个终端
chan.get_pty()
# 激活器
chan.invoke_shell()
while True:
# 使用select来检测,chan和sys.stdin这两个句柄有没有发生变化
# stdin用来处理用户的输入
# chan负责接收和上传
readable,writeable,error = select.select([chan,sys.stdin,],[],[],1)
if chan in readable:
try:
x = chan.recv(1024)
if len(x) == 0:
print '\r\n*** EOF\r\n',
break
sys.stdout.write(x)
sys.stdout.flush()
except socket.timeout:
pass
# 如果stdin中有内容,那么就发送给远端服务器
if sys.stdin in readable:
inp = sys.stdin.readable()
chan.sendall(inp)
chan.close()
tran.close()
上面代码的问题:用户输入内容后,只有点击回车,才会放到stdin中,才会发送给服务器端。
持久二:
更新tab补全功能,与标准模式个原生模式的转换
#!/usr/bin/env python
# coding:utf-8
import sys
import select
import socket
import paramiko
import termios
import tty
tran = paramiko.Transport(('192.168.56.12',22))
tran.start_client()
tran.auth_password('root','123456')
chan = tran.open_session()
chan.get_pty()
chan.invoke_shell()
# 获取原tty属性
oldtty = termios.tcgetattr(sys.stdin)
try:
# 为tty设置一个新的属性
# 默认的属性是:输入一行回车,然后执行
# crtl+C进程退出,遇到特殊字符,特殊处理
# 这是为原始模式,不认识所有特殊字符
# 放置特殊字符应该用在当前终端,将所有的用户输入均发送到远程服务器
tty.setraw(sys.stdin.fileno())
chan.settimeout(0.0)
while True:
# 监视 用户的输入和远程服务器返回数据
# 阻塞,知道句柄有内容可读
r,w,e = select.select([chan,sys.stdin],[],[],1)
if chan in r:
try:
x =chan.recv(1024)
if len(x)==0:
print '\r\n*** EOF\r\n',
break
except socket.timeout:
pass
if sys.stdin in r:
x = sys.stdin.read(1)
if len(x)==0:
break
chan.send(x)
finally:
# 重新将终端设置为标准的属性
termios.tcgetattr(sys.stdin,termios.TCSADRAIN,oldtty)
chan.close()
tran.close()