***环境是在Linux/Unix主机之间****
###需求
1、一台主机无密码登录其他主机进行操作(如同:SCRT)
2、不用登录其他主机就能实现主机命令执行
3、远程下载、上传文件
4、远程多并发上传、下载文件夹
5、操作方式类似于Linux scp/ssh命令操作
###主要使用工具及技术
1、paramiko模块的shell、sftp、ssh相关功能;
2、多进程并发;
3、进程队列与事件的结合使用;
4、使用到多进程子嵌套的方式完成功能;
5、内置模块logging的使用;
###工具使用方式及相关说明如下:
python sh_stp_main.py -xsh [email protected] (执行一个远程xshell终端)
python sh_stp_main.py -sh [email protected] 'df -h' (执行远程shell命令并返回结果)
python sh_stp_main.py -put 本地文件 [email protected]:远程文件/目录(上传文件到远程主机)
python sh_stp_main.py -get [email protected]:远程文件 本地文件/目录(从远程主机下载文件)
python sh_stp_main.py -putdir 本地文件/目录 [email protected]:远程文件/目录(上传文件/目录到远程主机)
python sh_stp_main.py -getdir [email protected]:远程文件/目录 本地文件/目录(下载文件/目录到本地主机)
在sh_stp_main.py的字典中定义主机相关信息;
主要控制模块如下,详细见GitHub源码项目:
# !/usr/bin/env python
__author__ = 'yuanwm <[email protected]>'
# -*- encoding: utf-8 -*-
from paramiko_sh import SSHConnection
from multistp import MultiSftp
import sys
'''
在这里定义IP与用户名以及密码,暂时使用字典定义(防止无第三方的模块解析配置文件)
'''
HostMsg = {
"[email protected]": {
"HostPassWord": "111111",
"HostPort": "22"
},
"[email protected]": {
"HostPassWord": "111111",
"HostPort": "22"
}
}
def get_host_msg(host_name_ip):
"""
根据用户名与ip获取主机的密码与端口信息
:param host_name_ip: 如:[email protected]
:return:
"""
# 获取密码
if host_name_ip not in HostMsg:
raise Exception('无主机[%s]信息!' % host_name_ip)
if "HostPassWord" not in HostMsg[HostNameIp]:
raise Exception('无主机[%s]密码配置信息!' % host_name_ip)
host_password = HostMsg[host_name_ip]["HostPassWord"]
if "HostPort" not in HostMsg[host_name_ip]:
raise Exception('无主机[%s]端口配置信息!' % host_name_ip)
host_port = HostMsg[host_name_ip]["HostPort"]
return host_password, host_port
if __name__ == "__main__":
'''
选择方式执行对应的操作
'''
# 传入参数判断,至少有两个参数:argv【1】 操作,argv[2]
if len(sys.argv) < 3:
sys.stderr.write('''执行方式错误!,例如:
python %s -xsh [email protected] (执行一个远程xshell终端)
python %s -sh [email protected] 'df -h' (执行远程shell命令并返回结果)
python %s -put 本地文件 [email protected]:远程文件/目录(上传文件到远程主机)
python %s -get [email protected]:远程文件 本地文件/目录(从远程主机下载文件)
python %s -putdir 本地文件/目录 [email protected]:远程文件/目录(上传文件/目录到远程主机)
python %s -getdir [email protected]:远程文件/目录 本地文件/目录(下载文件/目录到本地主机)
''' % (sys.argv[0], sys.argv[0], sys.argv[0], sys.argv[0], sys.argv[0], sys.argv[0]))
sys.stderr.flush()
exit(1)
# ip参数解析
OperaType = sys.argv[1]
try:
if OperaType == '-xsh': # xshell窗口
HostNameIp = sys.argv[2]
HostName = HostNameIp.split('@')[0]
HostIp = HostNameIp.split('@')[1]
(HostPassword, HostPort) = get_host_msg(HostNameIp)
ssh = SSHConnection(HostIp, HostPort, HostName, HostPassword)
ssh.connect()
ssh.x_shell()
ssh.disconnect()
elif OperaType == '-sh': # 执行远程shell命令
if len(sys.argv) < 4:
sys.stderr.write('''参数错误!,例如:
python %s -sh [email protected] 'df -h' (执行远程shell命令并返回结果)
''' % sys.argv[0])
sys.stderr.flush()
exit(1)
HostNameIp = sys.argv[2]
HostName = HostNameIp.split('@')[0]
HostIp = HostNameIp.split('@')[1]
(HostPassword, HostPort) = get_host_msg(HostNameIp)
command = sys.argv[3]
ssh = SSHConnection(HostIp, HostPort, HostName, HostPassword)
ssh.connect()
ssh.shell_cmd(command)
ssh.disconnect()
elif OperaType == '-put': # 上传文件
if len(sys.argv) < 4:
sys.stderr.write('''参数错误!,例如:
python %s -put 本地文件 [email protected]:远程文件/目录(上传文件到远程主机)
''' % sys.argv[0])
sys.stderr.flush()
exit(1)
RemoteMsg = sys.argv[3]
HostNameIp = RemoteMsg.split(':')[0]
HostName = HostNameIp.split('@')[0]
HostIp = HostNameIp.split('@')[1]
(HostPassword, HostPort) = get_host_msg(HostNameIp)
ssh = SSHConnection(HostIp, HostPort, HostName, HostPassword)
ssh.connect()
remote_path = RemoteMsg.split(':')[1]
local_path = sys.argv[2]
ssh.sftp_put(local_path, remote_path)
ssh.disconnect()
elif OperaType == '-get': # 下载文件
if len(sys.argv) < 5:
sys.stderr.write('''参数错误!,例如:
python %s -get [email protected]:远程文件 本地文件/目录(从远程主机下载文件)
''' % sys.argv[0])
sys.stderr.flush()
exit(1)
RemoteMsg = sys.argv[2]
HostNameIp = RemoteMsg.split(':')[0]
HostName = HostNameIp.split('@')[0]
HostIp = HostNameIp.split('@')[1]
(HostPassword, HostPort) = get_host_msg(HostNameIp)
ssh = SSHConnection(HostIp, HostPort, HostName, HostPassword)
ssh.connect()
remote_path = RemoteMsg.split(':')[1]
local_path = sys.argv[3]
ssh.sftp_get(remote_path, local_path)
ssh.disconnect()
elif OperaType == '-getdir': # 下载目录
if len(sys.argv) < 4:
sys.stderr.write('''参数错误!,例如:
python %s -getdir [email protected]:远程文件/目录 本地文件/目录(下载文件/目录到本地主机)
''' % sys.argv[0])
sys.stderr.flush()
exit(1)
RemoteMsg = sys.argv[2]
HostNameIp = RemoteMsg.split(':')[0]
HostName = HostNameIp.split('@')[0]
HostIp = HostNameIp.split('@')[1]
(HostPassword, HostPort) = get_host_msg(HostNameIp)
remote_path = RemoteMsg.split(':')[1]
local_path = sys.argv[3]
# 最大进程数定义
max_process_num = 0
if len(sys.argv) > 4:
max_process_num = int(sys.argv[4])
else:
max_process_num = 5
multi_sftp = MultiSftp(HostIp, HostPort, HostName, HostPassword)
multi_sftp.sftp_get_dir(local_path, remote_path, max_process_num)
elif OperaType == '-putdir': # 上传目录
if len(sys.argv) < 4:
sys.stderr.write('''参数错误!,例如:
python %s -putdir 本地文件/目录 [email protected]:远程文件/目录(上传文件/目录到远程主机)
''' % sys.argv[0])
sys.stderr.flush()
exit(1)
RemoteMsg = sys.argv[3]
HostNameIp = RemoteMsg.split(':')[0]
HostName = HostNameIp.split('@')[0]
HostIp = HostNameIp.split('@')[1]
(HostPassword, HostPort) = get_host_msg(HostNameIp)
remote_path = RemoteMsg.split(':')[1]
local_path = sys.argv[2]
# 最大进程数定义
max_process_num = 0
if len(sys.argv) > 4:
max_process_num = int(sys.argv[4])
else:
max_process_num = 5
multi_sftp = MultiSftp(HostIp, HostPort, HostName, HostPassword)
multi_sftp.sftp_put_dir(local_path, remote_path, max_process_num)
else:
sys.stderr.write("不支持操作类型[%s]\n" % OperaType)
sys.stderr.flush()
exit(1)
except Exception as ErrMsg:
sys.stderr.write('操作[%s]执行错误![%s]\n' % (ErrMsg, OperaType))
sys.stderr.flush()
exit(1)