服务器简快速拷贝文件,easy-copy服务器文件拷贝简易小工具

这是一个使用Python的paramiko库实现的SSH文件传输工具,可以将源主机的文件通过SCP协议复制到多个目标主机,并进行MD5校验确保文件一致性。程序首先检查目标主机是否存在相同文件,如果存在则根据配置决定是否覆盖或备份。然后,源文件被压缩并传输,再在目标主机上解压并验证MD5。如果MD5不一致,会撤回传输的包。整个过程支持详细日志输出和压缩选项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import os

import sys

import time

import paramiko as pm

'''

host格式:

{

"ip":"127.0.0.1",

"port":22,

"username":"root",

"password":"123456",

"file":"filename"

}

dst为host列表

要求:

源主机需要部署sshpass、scp

本机需要python3.4及以上,以及安装paramiko库

各源主机及目的主机能互联互通,ssh安全连接过

'''

# 默认运行配置:源

example_src = {

"ip": "10.112.98.132",

"port": 22,

"username": "root",

"password": "111",

"file": "/root/111.o"

}

# 默认运行配置:目的,数组

example_dst = [

{

"ip": "10.112.98.134",

"port": 22,

"username": "root",

"password": "222",

"file": "/root/222.o"

},

{

"ip": "10.112.98.151",

"port": 22,

"username": "root",

"password": "333",

"file": "/root/333.o"

},

{

"ip": "10.112.96.67",

"port": 22,

"username": "root",

"password": "444",

"file": "/root/111.o"

}

]

# 显示详细信息

# detail = False

detail = True

def do_copy(src_host, src_ssh, src_md5, dst_host, srcfile, compress=True, force=False, packname=".tarxjb"):

print()

print("*****cp*****")

print()

dst_ssh = create_ssh(dst_host)

# dst_ssh.exec_command('ssh -o "StrictHostKeyChecking no" {name}@{ip}'.format(name=src_host["username"],ip=src_host["ip"]))

# 检查对方是否已存在相同名字文件

if check_exist(dst_ssh, dst_host["file"]):

# 存在相同,判断是否强制覆盖,不覆盖则自动备份

if detail:

print("res:exist a same name file")

if not force:

if detail:

print("res:do backup")

backup_file_cmd = "mv {file} {file}.x.backup".format(

file=dst_host["file"])

dst_ssh.exec_command(backup_file_cmd)

# 传输文件指令

scp_cmd = "sshpass -p {pw} scp -P {port} {sfile} {duser}@{dip}:{dfile}".format(

port=dst_host["port"], pw=dst_host["password"], sfile=srcfile+packname, duser=dst_host["username"], dip=dst_host["ip"], dfile=srcfile+packname)

sin, sout, serr = src_ssh.exec_command(scp_cmd)

if detail:

print(sout.read().decode())

else:

sout.read().decode()

if detail:

print("res:scp done")

dst_md5 = compu_md5(dst_ssh, srcfile+packname)

if dst_md5 is None:

# md5计算失败

if detail:

print("err:md5 failed")

del_pack(dst_ssh, srcfile+packname)

return False

if src_md5 != dst_md5:

# md5不同,需要撤回包

if detail:

print("err:md5 is not consist")

del_pack(dst_ssh, srcfile+packname)

return False

# input("ddd")

res = compu_tar(dst_ssh, file=srcfile, type="x",

compress=compress, packname=packname)

# input("ddd")

if detail:

print("res:dst tar success")

if not res:

# 解压失败,需要撤回包

if detail:

print("err:tar failed")

del_pack(dst_ssh, srcfile+packname)

return False

if detail:

print("res:file check success")

# 删除中间包

# input("ddd")

del_pack(dst_ssh, srcfile+packname)

if detail:

print("res:remove dst temp pack success")

# 修改文件名

# input("ddd")

mv_file_cmd = "mv {file1} {file2}".format(

file1=srcfile, file2=dst_host["file"])

dst_ssh.exec_command(mv_file_cmd)

if detail:

print("res:filename update success")

dst_ssh.close()

if detail:

print("ok: {file} done".format(file=dst_host["file"]))

return True

def copy(src_host, dst, compress=True, force=False):

# 复制文件,一对多

# 获取于源ip的ssh链接

src_ssh = create_ssh(src_host)

# 确定压缩参数

gzip = ""

if compress:

gzip = "z"

# 判断文件是否存在

res = check_exist(src_ssh, src_host["file"])

if detail:

print("src file exist? "+str(res))

# 执行压缩、打包命令

packname = "." + str(int(time.time())) + ".tarxjb"

res = compu_tar(src_ssh, src_host["file"],

"c", compress=compress, packname=packname)

if detail:

print("res:tar success? "+str(res))

# 计算原文件md5值

src_md5 = compu_md5(src_ssh, src_host["file"]+packname)

if detail:

print("src md5 :"+str(src_md5))

# 执行复制操作

res_cp = []

for row in dst:

res_cp.append({row["file"]: do_copy(

src_host, src_ssh, srcfile=src_host["file"], src_md5=src_md5, dst_host=row, packname=packname)})

# 删除本地临时文件

# input("ddd")

del_pack(src_ssh, src_host["file"]+packname)

if detail:

print("res:remove src temp pack success")

print()

print("*****res*****")

for index in res_cp:

print(index)

print("*****res*****")

print()

print("ok: all done!")

src_ssh.close()

def del_pack(ssh, file):

# 删除中间包

del_cmd = "rm -f {file}".format(file=file)

sin, sout, serr = ssh.exec_command(del_cmd)

if detail:

print("cmd: rm "+sout.read().decode())

def create_ssh(host):

# 创建ssh链接

ssh = pm.SSHClient()

ssh.set_missing_host_key_policy(pm.AutoAddPolicy())

ssh.connect(hostname=host["ip"], port=host["port"],

username=host["username"], password=host["password"])

return ssh

def compu_tar(ssh, file, type="c", compress=True, packname=".tarxjb"):

# 打包及解包

# gzip表示是否要用gzip压缩,默认压缩

gzip = ""

if compress:

gzip = "z"

# 打包指令

tar_cmd = "tar c{gzip}vfpP {file}{packname} {file} 2>/dev/null".format(

gzip=gzip, file=file, packname=packname)

# 解包指令

if type == "x":

tar_cmd = "tar x{gzip}vfpP {file}{packname} 2>/dev/null".format(

gzip=gzip, file=file, packname=packname)

if detail:

print("cmd: tar: " + tar_cmd)

stdin, stdout, stderr = ssh.exec_command(tar_cmd)

res = stdout.read().decode()

if res == "":

if detail:

print("err: {file}{packname} tar failed".format(

file=file, packname=packname))

return False

return True

def check_exist(ssh, file):

# 检查文件是否存在

exist_cmd = "find {file} 2>/dev/null".format(file=file)

stdin, stdout, stderr = ssh.exec_command(exist_cmd)

res = stdout.read().decode()

if res == "":

if detail:

print("res: {file} is not exist".format(file=file))

return False

else:

if detail:

print("res: {file} is exist".format(file=file))

return True

def compu_md5(ssh, file):

# 计算文件md5

src_md5_cmd = "md5sum {file} 2>/dev/null | awk \'{{print $1}}\'".format(

file=file)

stdin, stdout, stderr = ssh.exec_command(src_md5_cmd)

src_md5 = stdout.read().decode()

if detail:

print("cmd: md5 :"+src_md5_cmd)

print("res: cmd md5 res : "+src_md5)

if src_md5 == "":

if detail:

print("err: {file} md5 or tar failed".format(file=file))

src_md5 = None

else:

if detail:

print("res: {file} md5 : {md5}".format(file=file, md5=src_md5))

return src_md5

if __name__ == "__main__":

print("easy tar tool")

copy(example_src, example_dst, compress=True)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值