1.简介
paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。
由于使用的是python这样的能够跨平台运行的语言,所以所有python支持的平台,如Linux, Solaris, BSD, MacOS X, Windows等,paramiko都可以支持,因此,如果需要使用SSH从一个平台连接到另外一个平台,进行一系列的操作时,paramiko是最佳工具之一。
举个常见的例子,现有这样的需求:需要使用windows客户端,远程连接到Linux服务器,查看上面的日志状态,大家通常使用的方法会是:
1:用telnet
2:用PUTTY
3:用WinSCP
4:用XManager等…
那现在如果需求又增加一条,要从服务器上下载文件,该怎么办?那常用的办法可能会是:
1:Linux上安装FTP并配置
2:Linux上安装Sambe并配置…
大家会发现,常见的解决方法都会需要对远程服务器必要的配置,如果远程服务器只有一两台还好说,如果有N台,还需要逐台进行配置,或者需要使用代码进行以上操作时,上面的办法就不太方便了。
使用paramiko可以很好的解决以上问题,比起前面的方法,它仅需要在本地上安装相应的软件(python以及PyCrypto),对远程服务器没有配置要求,对于连接多台服务器,进行复杂的连接操作特别有帮助。
2.paramiko远程密码连接
# 基于ssh用于连接远程服务器做操作:远程执行命令, 上传文件, 下载文件
import paramiko
# ssh [email protected]
# 创建一个ssh对象;
client = paramiko.SSHClient()
# 2. 解决问题:如果之前没有;连接过的ip, 会出现
# Are you sure you want to continue connecting (yes/no)? yes
# 自动选择yes
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 3. 连接服务器
client.connect(hostname='172.25.254.46',
port=22,
username='root',
password='westos')
# 4. 执行操作
stdin, stdout, stderr = client.exec_command('hostnaewdeme')
# 5. 获取命令的执行结果;
result = stdout.read().decode('utf-8')
print(result)
print(stderr.read())
# 6. 关闭连接
client.close()
3.paramiko批量连接操作
# 基于ssh用于连接远程服务器做操作:远程执行命令, 上传文件, 下载文件
import paramiko
import logging
from paramiko.ssh_exception import NoValidConnectionsError, AuthenticationException
def connect(cmd, hostname, port=22, username='root', password='westos'):
# ssh [email protected]
# 创建一个ssh对象;
client = paramiko.SSHClient()
# 2. 解决问题:如果之前没有;连接过的ip, 会出现
# Are you sure you want to continue connecting (yes/no)? yes
# 自动选择yes
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
# 3. 连接服务器
client.connect(hostname=hostname,
port=port,
username=username,
password=password)
print("正在连接主机%s......." %(hostname))
except NoValidConnectionsError as e:
print("连接失败")
except AuthenticationException as e:
print("密码错误")
else:
# 4. 执行操作
stdin, stdout, stderr = client.exec_command(cmd)
# 5. 获取命令的执行结果;
result = stdout.read().decode('utf-8')
print(result)
# 6. 关闭连接
client.close()
with open('host.txt') as f:
for line in f:
line = line.strip()
hostname, port, username, password = line.split(':')
print(hostname.center(50, '*'))
connect('hostname', hostname, port, username, password)
4.paramiko基于公钥密钥连接
# 基于ssh用于连接远程服务器做操作:远程执行命令, 上传文件, 下载文件
import paramiko
from paramiko.ssh_exception import NoValidConnectionsError, AuthenticationException
def connect(cmd, hostname, port=22, user='root'):
# ssh [email protected]
# 创建一个ssh对象;
client = paramiko.SSHClient()
# 返回一个私钥对象
private_key = paramiko.RSAKey.from_private_key_file('id_rsa')
# 2. 解决问题:如果之前没有;连接过的ip, 会出现
# Are you sure you want to continue connecting (yes/no)? yes
# 自动选择yes
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
# 3. 连接服务器
client.connect(hostname=hostname,
port=port,
username=user,
pkey=private_key
)
# 4. 执行操作
stdin, stdout, stderr = client.exec_command(cmd)
except NoValidConnectionsError as e:
print("连接失败")
except AuthenticationException as e:
print("密码错误")
else:
# 5. 获取命令的执行结果;
result = stdout.read().decode('utf-8')
print(result)
finally:
# 6. 关闭连接
client.close()
for count in range(254):
host = '172.25.254.%s' %(count+1)
print(host.center(50, '*'))
connect('uname', host)
5.基于密钥的上传下载
import paramiko
# 返回一个私钥对象
private_key = paramiko.RSAKey.from_private_key_file('id_rsa')
transport = paramiko.Transport(('172.25.254.39', 22))
transport.connect(username='root',pkey=private_key)
sftp = paramiko.SFTPClient.from_transport(transport)
# 上传文件, 包含文件名
sftp.put('/tmp/kiosk', '/mnt/kiosk2')
sftp.get('/mnt/kiosk2', '/home/kiosk/Desktop/day18/kiosk')
transport.close()
6.paramiko再次封装
import os
import paramiko
from paramiko.ssh_exception import NoValidConnectionsError, AuthenticationException, SSHException
class SshRemoteHost(object):
def __init__(self, hostname, port, user, passwd, cmd):
# 指的不是shell命令
# cmd shell命令
# put
# get
self.hostname = hostname
self.port = port
self.user = user
self.passwd = passwd
self.cmd = cmd
def run(self):
"""默认调用的内容"""
# cmd hostname
# put
# get
cmd_str = self.cmd.split()[0] # cmd
# 类的反射, 判断类里面是否可以支持该操作?
if hasattr(self, 'do_'+ cmd_str): # do_cmd
getattr(self, 'do_'+cmd_str)()
else:
print("目前不支持该功能")
def do_cmd(self):
# 创建一个ssh对象;
client = paramiko.SSHClient()
# 2. 解决问题:如果之前没有;连接过的ip, 会出现
# Are you sure you want to continue connecting (yes/no)? yes
# 自动选择yes
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
# 3. 连接服务器
client.connect(hostname=self.hostname,
port=self.port,
username=self.user,
password=self.passwd)
print("正在连接主机%s......." % (self.hostname))
except NoValidConnectionsError as e:
print("连接失败")
except AuthenticationException as e:
print("密码错误")
else:
# 4. 执行操作
# cmd uname
# cmd ls /etc/
# *******注意:
cmd = ' '.join(self.cmd.split()[1:])
stdin, stdout, stderr = client.exec_command(cmd)
# 5. 获取命令的执行结果;
result = stdout.read().decode('utf-8')
print(result)
# 6. 关闭连接
client.close()
def do_put(self):
# put /tmp/passwd /tmp/passwd
# put /tmp/passwd /tmp/pwd
# put /tmp/passwd # 将本机的/tmp/passwd文件上传到远程主机的/tmp/passwd;
print("正在上传.....")
try:
transport = paramiko.Transport((self.hostname, int(self.port)))
transport.connect(username=self.user, password=self.passwd)
except SSHException as e:
print("连接失败")
else:
sftp = paramiko.SFTPClient.from_transport(transport)
newCmd = self.cmd.split()[1:]
if len(newCmd) == 2:
# 上传文件, 包含文件名
sftp.put(newCmd[0], newCmd[1])
print("%s文件上传到%s主机的%s文件成功" %(newCmd[0],
self.hostname, newCmd[1]))
else:
print("上传文件信息错误")
transport.close()
def do_get(self):
print("正在下载.....")
# 2. 根据选择的主机组, 显示包含的主机IP/主机名;
# 3. 让用户确认信息, 选择需要批量执行的命令;
# - cmd shell命令
# - put 本地文件 远程文件
# - get 远程文件 本地文件
def main():
# 1. 选择操作的主机组:eg: mysql, web, ftp
groups = [file.rstrip('.conf') for file in os.listdir('conf')]
print("主机组显示:".center(50, '*'))
for group in groups: print('\t', group)
choiceGroup = input("清选择批量操作的主机组(eg:web):")
# 2. 根据选择的主机组, 显示包含的主机IP/主机名;
# 1). 打开文件conf/choiceGroup.conf
# 2). 依次读取文件每一行,
# 3). 只拿出ip
print("主机组包含主机:".center(50, '*'))
with open('conf/%s.conf' %(choiceGroup)) as f:
for line in f:
print(line.split(':')[0])
f.seek(0,0) # 把指针移动到文件最开始
hostinfos = [line.strip() for line in f.readlines()]
# 3. 让用户确认信息, 选择需要批量执行的命令;
print("批量执行脚本".center(50, '*'))
while True:
cmd = input(">>:").strip() # cmd uname
if cmd:
if cmd == 'exit' or cmd =='quit':
print("执行结束, 退出中......")
break
# 依次让该主机组的所有主机执行
for info in hostinfos:
# 'ip:port:user:passwd'
host, port, user, passwd = info.split(":")
print(host.center(50, '-'))
clientObj = SshRemoteHost(host, port, user, passwd, cmd)
clientObj.run()
if __name__ == '__main__':
main()