一、paramiko模块的介绍
SSH协议基于python的实现 ,会返回标准输入、标准输出、标准错误输出三个值
作用:
1、执行远程命令
2、文件上传、下载
安装模块
> pip install paramiko
一、执行远程命令
import paramiko
def exeCMD():
# 创建ssh客户端工具
ssh_client = paramiko.SSHClient()
# 设置丢失主机密钥的策略为自动添加
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
# 连接服务器
ssh_client.connect(hostname="192.168.183.10", port=22, username="root", password="redhat")
# 远程执行命令, 返回三个特殊文件; 依次是标准输入、标准输出、标准错误输出
stdin, stdout, stderr = ssh_client.exec_command("df -hT")
print(stdout.read().decode("utf-8"))
ssh_client.close()
if __name__ == '__main__':
exeCMD()
示例: 批量执行命令
import paramiko
import sys
import pymysql
import hashlib
import getpass
# 连接数据库,获取服务器信息
def getServerInfo():
try:
dbconn = pymysql.connect(host="172.31.2.252",user="admin", password="redhat", database="testdb")
except Exception as e:
print("数据库连接失败")
print(e)
sys.exit()
cr = dbconn.cursor()
query_all_server_sql = "select * from servers"
result = cr.execute(query_all_server_sql)
if result != 0:
all_server = cr.fetchall()
return all_server
cr.close()
dbconn.close()
# 连接服务器执行命令,输出结果
def exeCMD(ip, user, pwd, cmd, port=22):
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
try:
ssh_client.connect(hostname=ip, username=user, password=pwd, port=port)
except Exception as e:
print("创建ssh连接失败,检查认证信息")
print(e)
sys.exit()
stdin,stdout,stderr = ssh_client.exec_command(cmd)
print(stdout.read().decode("utf-8"))
ssh_client.close()
# 使用md5算法加密算法
def encryptPWD(password):
md5 = hashlib.md5()
md5.update(password.encode("utf-8"))
return md5.hexdigest()
if __name__ == '__main__':
all_server = getServerInfo()
cmd = input("命令: ").strip()
for server_id, server_ip, server_user, server_pwd, server_ssh_port in all_server:
print("服务器'%s'执行'%s'命令" % (server_ip, cmd))
password = getpass.getpass("密码: ")
password_encrypt = encryptPWD(password=password)
if password_encrypt == server_pwd:
exeCMD(ip=server_ip, user=server_user, pwd=password, port=server_ssh_port, cmd=cmd)
else:
print("密码错误")
二、文件上传、下载
import paramiko
def fileOP():
# 创建ssh连接
sshconn = paramiko.Transport(("192.168.183.10", 22))
sshconn.connect(username="root", password="redhat")
# 基于ssh连接创建ftp客户端
ftpclient = paramiko.SFTPClient.from_transport(sshconn)
# 下载文件
# ftpclient.get("/etc/fstab", r"E:\project01\files\fstab")
# 上传文件
ftpclient.put(r"E:\project01\files\test_new.sql", "/tmp/test_new.sql")
ftpclient.close()
sshconn.close()
示例:批量上传文件
import paramiko
import sys
import hashlib
import os
from util.exeCMDBySSH import getServerInfo
# 获取本地文件的MD5校验码
def getLocalFileMD5(file_name):
md5 = hashlib.md5()
with open(file_name, mode="rb") as fobj:
while True:
data = fobj.read(4096)
if data:
md5.update(data)
else:
break
return md5.hexdigest().strip()
# 获取指定服务器上的指定文件的MD5校验码
def getRemoteFileMD5(ip, user, pwd, file_name, port=22):
sshclient = paramiko.SSHClient()
sshclient.set_missing_host_key_policy(paramiko.AutoAddPolicy)
try:
sshclient.connect(hostname=ip, username=user, password=pwd, port=port)
except Exception as e:
print("ssh连接建立失败")
print(e)
sys.exit()
get_md5_cmd = "md5sum %s | awk '{print $1}'" % file_name
stdin, stdout,stderr = sshclient.exec_command(get_md5_cmd)
return stdout.read().decode("utf-8").strip()
sshclient.close()
# 向指定的服务器上传指定的文件 # source_file: E:\project01\files\test01.sql, dest_dir: /etc
def uploadFile(ip, user, pwd, source_file, dest_dir, port=22):
# 获取服务器上目的文件名称
if dest_dir.endswith("/"):
dest_file_name = dest_dir + os.path.basename(source_file)
else:
dest_file_name = dest_dir + "/" + os.path.basename(source_file)
# 创建ssh连接
try:
sshconn = paramiko.Transport((ip, port))
except Exception as e:
print("ssh连接建立失败, 检查地址、端口是否正确")
print(e)
sys.exit()
# 进行用户认证
try:
sshconn.connect(username=user, password=pwd)
except Exception as e:
print("ssh连接建立失败,检查用户名、密码")
print(e)
sys.exit()
ftpclient = paramiko.SFTPClient.from_transport(sshconn)
ftpclient.put(source_file, dest_file_name)
ftpclient.close()
sshconn.close()
if __name__ == '__main__':
all_server = getServerInfo()
source_file = input("源文件: ")
dest_dir = input("服务器目录: ")
if os.path.exists(source_file):
# 获取源文件的校验码
source_file_md5 = getLocalFileMD5(source_file)
for server_id, server_ip, server_user, server_pwd, server_port in all_server:
uploadFile(ip=server_ip, user=server_user, pwd=server_pwd, port=int(server_port), source_file=source_file, dest_dir=dest_dir)
# 获取上传到服务器上的文件名称
dest_file_name = dest_dir + "/" + os.path.basename(source_file)
remote_file_md5 = getRemoteFileMD5(ip=server_ip, user=server_user, pwd=server_pwd, port=server_port, file_name=dest_file_name)
print("源文件'%s'的校验码: %s" % (source_file, source_file_md5))
print("服务器'%s'上的'%s'文件的校验码: %s" % (server_ip, dest_file_name, remote_file_md5))
if source_file_md5 == remote_file_md5:
print("上传成功")
else:
print("上传失败")
print("----" * 10)