1、对机器进行分组
2、对指定组的机器进行批量操作(执行某条命令,上传下载文件)
3、要有操作日志
#!/usr/bin/env python3
import sys, paramiko, os, time, pickle
from multiprocessing import Process, Lock
import logging
logging.basicConfig(filename='dingyi.log', level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%Y-%d-%m %I:%M:%S %p')
class Dingyi(object): #定义远程传输文件和执行命令的类
def __init__(self, ip):
self.ip = ip
self.port = 22
self.name = 'root'
self.password = '111111'
def link(self): #连接
#self.ssh = paramiko.SSHClient()
#self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#self.ssh.connect(hostname = self.ip, username = 'root', password = '111111')
self.transport = paramiko.Transport((self.ip, self.port))
self.transport.connect(username = self.name, password = self.password)
self.ssh = paramiko.SSHClient()
self.ssh._transport = self.transport
logging.info("connect %s" % self.ip)
self.sftp = paramiko.SFTPClient.from_transport(self.transport)
def close(self): #断开链接
self.transport.close()
logging.info("close %s" % self.ip)
def cmd(self, user_cmd): #执行命令
stdin, stdout, stderr = self.ssh.exec_command(user_cmd)
result = str(stdout.read().decode())
res_err = str(stderr.read().decode())
if not res_err:
logging.info("bash %s at %s success" % (user_cmd, self.ip))
return result
else:
logging.warning("bash %s at %s fail" % (user_cmd, self.ip))
return res_err
def put(self, local_file_name, target_file_name): #上传文件
try:
self.sftp.put(local_file_name, target_file_name)
logging.info("put %s to %s" % (local_file_name, target_file_name))
except IsADirectoryError:
print("%s文件读取错误,请输入文件\n" % local_file_name)
logging.error("put:%s文件读取错误" % local_file_name )
except FileNotFoundError:
print("%s文件没有找到\n" % local_file_name)
logging.error("put:%s文件没有找到" % local_file_name)
except OSError:
print("%s目标目录不是文件\n" % target_file_name)
logging.error("put:%s目标目录不是文件" % target_file_name)
def get(self, target_file_name, local_file_name): #下载文件
try:
self.sftp.get(target_file_name, local_file_name)
logging.info('get %s to %s' % (target_file_name, local_file_name))
except IsADirectoryError:
print("%s文件读取错误,请输入文件" % local_file_name)
logging.error("get:%s文件读取错误" % local_file_name )
except FileNotFoundError:
print("%s文件没有找到" % local_file_name)
logging.error("get:%s文件读取错误" % local_file_name )
except OSError:
print("%s目标目录不是文件" % target_file_name)
logging.error("get:%s文件读取错误" % local_file_name )
def putdir(self, local_dir, target_dir): #上传目录
try:
dir_list = os.listdir(local_dir) #检查本地目录,获取目录内所有目录和文件
except FileNotFoundError:
print("没有找到此目录%s 或目标目录不正确" % local_dir)
logging.error("putdir:没有找到此目录%s 或目标目录不正确" % local_dir)
sys.exit()
except NotADirectoryError:
print("%s这不是个目录 或目标目录不正确" % local_dir)
logging.error("putdir:%s这不是个目录 或目标目录不正确" % local_dir)
sys.exit()
for i in dir_list: #遍历目录内容
if local_dir[-1] != os.sep: #检查目录末尾是否有'/'
local_dir += os.sep
if target_dir[-1] != os.sep:
target_dir += os.sep
local_file = local_dir + i #将目录拼接成子目录
target_file = target_dir + i
if os.path.isdir(local_file): #如果子目录是文件,则递归
target_dir_temp = target_dir + i
local_dir_temp = local_dir + i
cmd2 = "mkdir %s" % target_dir_temp
a,b,c = self.ssh.exec_command(cmd2)
time.sleep(0.1) #这里要暂停一下,因为在远程的时候,上传文件要比创建子目录快
self.putdir(local_dir_temp, target_dir_temp)
else: #是文件,上传文件
self.put(local_file, target_file)
def getdir(self, target_dir, local_dir):
user_cmd = "ls -l %s" % target_dir #获取远程目录信息
res = self.cmd(user_cmd).strip()
for i in res.split('\n'): #遍历远程目录
if target_dir[-1] != os.sep: #判断目录结尾是否有'/'
target_dir = target_dir + os.sep
if local_dir[-1] != os.sep:
local_dir = local_dir + os.sep
if i[0] == 'd': #如果是目录,在本地创建目录,并递归
dir_name = i.split()[-1]
target_dir_temp = target_dir + dir_name
local_dir_temp = local_dir + dir_name
os.makedirs(local_dir_temp)
self.getdir(target_dir_temp, local_dir_temp)
elif i[0] == '-': #如果是文件,下载文件
file_name = i.split()[-1]
target_file_name = target_dir + file_name
local_file_name = local_dir + file_name
self.get(target_file_name, local_file_name)
def get_group(group_name): #获取机器IP地址组
with open("group", 'rb') as f:
group_dict = pickle.load(f)
try:
return group_dict[group_name]
except KeyError:
return '输入的组名错误'
def help(): #帮助文档
title = '''
输入错入
应输入 python3 dingyi -g 组名 -选项
选项可以是:
-cmd 命令
-put 本地文件 远程目标文件
-get 远程目标文件 本地文件
-putdir 本地目录 远程目标目录
-getdir 远程目标目录 本地目录
'''
print(title)
def get_user_cmd(target_ip, l): #分析用户输入的命令
l.acquire() #进程锁
#当选项存在时,完成相应的操作
if '-cmd' in sys.argv:
cmd_index = sys.argv.index('-cmd')
try: #判断参数是否正确
user_cmd = sys.argv[cmd_index + 1]
except IndexError:
help()
sys.exit()
rel_cmd(target_ip, user_cmd)
if '-get' in sys.argv:
get_index = sys.argv.index('-get')
try:
target_file_name = sys.argv[get_index + 1]
local_file_name = sys.argv[get_index + 2]
except IndexError:
help()
sys.exit()
rel_get(target_ip, target_file_name, local_file_name)
if '-put' in sys.argv:
put_index = sys.argv.index('-put')
try:
local_file_name = sys.argv[put_index + 1]
target_file_name = sys.argv[put_index + 2]
except IndexError:
help()
sys.exit()
rel_put(target_ip, local_file_name, target_file_name)
if '-getdir' in sys.argv:
getdir_index = sys.argv.index('-getdir')
try:
target_dir = sys.argv[getdir_index + 1]
local_dir = sys.argv[getdir_index + 2]
except IndexError:
help()
sys.exit()
rel_getdir(target_ip, target_dir, local_dir)
if '-putdir' in sys.argv:
putdir_index = sys.argv.index('-putdir')
try:
local_dir = sys.argv[putdir_index + 1]
target_dir = sys.argv[putdir_index + 2]
except IndexError:
help()
sys.exit()
rel_putdir(target_ip, local_dir, target_dir)
l.release() #解锁
def rel_cmd(target_ip, user_cmd): #命令操作
dingyi = Dingyi(target_ip)
dingyi.link()
res = dingyi.cmd(user_cmd)
dingyi.close()
print(res)
def rel_put(target_ip, local_file_name, target_file_name): #上传文件操作
dingyi = Dingyi(target_ip)
dingyi.link()
dingyi.put(local_file_name, target_file_name)
dingyi.close()
def rel_get(target_ip, target_file_name, local_file_name): #下载文件操作
dingyi = Dingyi(target_ip)
dingyi.link()
dingyi.get(target_file_name, local_file_name)
dingyi.close()
def rel_getdir(target_ip, target_dir, local_dir):#下载目录操作
dingyi = Dingyi(target_ip)
dingyi.link()
dingyi.getdir(target_dir, local_dir)
dingyi.close()
def rel_putdir(target_ip, local_dir, target_dir):#上传目录操作
dingyi = Dingyi(target_ip)
dingyi.link()
dingyi.putdir(local_dir, target_dir)
dingyi.close()
def run(): #程序主体
if '-g' in sys.argv: #判断是否输入主机组
group_index = sys.argv.index('-g')
group_name = sys.argv[group_index + 1]
else:
help()
sys.exit()
#判断是否输入参数
if '-cmd' not in sys.argv and '-put' not in sys.argv and '-get' not in sys.argv and '-putdir' not in sys.argv and '-getdir' not in sys.argv:
help()
sys.exit()
ip_list = get_group(group_name)
l = Lock()
process_list = []
for i in ip_list:
t = Process(target = get_user_cmd, args = (i,l, ))
process_list.append(t)
for i in process_list:
i.start()
if __name__ == "__main__":
run()