并行命令

需求:创建脚本工具,用于对服务器的批量检查

1、使用多线程加消息队列形式:

import paramiko
import threading
import sys
import queue


#生产者
class ProSSH(threading.Thread):
def __init__(self, ips, queue):
threading.Thread.__init__(self) #继承父类的初始化方法
self.queue = queue
self.ips = ips

def run(self): #重写run方法
for ip in self.ips:
self.queue.put(ip)


#消费者
class CusSSH(threading.Thread):
def __init__(self, cmd, queue):
threading.Thread.__init__(self) #继承父类的初始化方法
self.queue = queue
self.cmd = cmd

def run(self):
try:
lock.acquire()
ip = self.queue.get(1, 5) # 阻塞5秒
self.ssh_conn(ip)
lock.release()
except:
return

def ssh_conn(self, ip):
ssh = paramiko.SSHClient() # 创建链接对象
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 指定当对方主机没有本机公钥的情况时应该怎么办,AutoAddPolicy表示自动在对方主机保存下本机的秘钥
pkey_file = '/root/.ssh/id_rsa' # 指定私钥位置
key = paramiko.RSAKey.from_private_key_file(pkey_file, password='123456') # 创建秘钥链接对象,密码为创建秘钥时设置的,没有设置就留空
try:
ssh.connect(hostname=ip, username='root', pkey=key, timeout=1)
except:
print("Timeout or not parmission")
return 1
stdin, stdout, stderr = ssh.exec_command(self.cmd) # 输出会分别保存到三个文件里
stdout = stdout.read()[:-1] # [:-1]指的是去掉最后一个字符,因为这个最后输出会有个换行符
stderr = stderr.read()[:-1]
if stdout:
print("{0}: {1}".format(ip, stdout))
ssh.close()
else:
print("{0}: {1}".format(ip, stderr))
ssh.close()

if __name__ == '__main__':
paramiko.util.log_to_file('/root/python/paramikos/paramiko.log') # 输出日志
queue = queue.Queue(10) # 创建消息队列,最大长度10
lock = threading.Lock()
ips = ['192.168.137.' + str(i) for i in range(10, 101)]
try:
cmd = sys.argv[1]
except Exception as e:
print("{0} follow a command".format(__file__))
sys.exit(1)
t1 = ProSSH(ips, queue)
t1.start()
for i in range(len(ips)):
t2 = CusSSH(cmd, queue)
t2.start()

2、使用进程池形式:

import paramiko
import multiprocessing
import sys


def ssh_conn(ip, cmd):
ssh = paramiko.SSHClient() # 创建链接对象
ssh.set_missing_host_key_policy(
paramiko.AutoAddPolicy()) # 指定当对方主机没有本机公钥的情况时应该怎么办,AutoAddPolicy表示自动在对方主机保存>下本机的秘钥
pkey_file = '/root/.ssh/id_rsa' # 指定私钥位置
key = paramiko.RSAKey.from_private_key_file(pkey_file, password='123456') # 创建秘钥链接对象,密码为创建秘钥时设置的,没有设置就留空
try:
ssh.connect(hostname=ip, username='root', pkey=key, timeout=1)
except:
print("Timeout or not parmission")
return 1
stdin, stdout, stderr = ssh.exec_command(cmd) # 输出会分别保存到三个文件里
stdout = stdout.read()[:-1] # [:-1]指的是去掉最后一个字符,因为这个最后输出会有个换行符
stderr = stderr.read()[:-1]
if stdout:
print("{0}: {1}".format(ip, stdout))
ssh.close()
else:
print("{0}: {1}".format(ip, stderr))
ssh.close()

if __name__ == '__main__':
paramiko.util.log_to_file('/root/python/paramikos/paramiko.log') # 输出日志
ips = ['192.168.137.' + str(i) for i in range(10, 101)]
try:
cmd = sys.argv[1]
except Exception as e:
print("{0} follow a command".format(__file__))
sys.exit(1)
pool = multiprocessing.Pool(processes=10) #开启10个进程池
for ip in ips:
pool.apply_async(func=ssh_conn, args=(ip, cmd)) #异步进程
pool.close()
pool.join() #阻塞主进程

3、使用进程池加参数形式:

import paramiko
import multiprocessing
import sys
from optparse import OptionParser


def opt():
parser = OptionParser("Usage: %prog -a command")
parser.add_option('-a',
dest = 'addr',
action = 'store',
help = 'ip or iprange, EX: 192.168.1.1,192.168.1.3 or 192.168.1.1-192.168.1.3')
options, args = parser.parse_args()
return options, args

def parseOpt(option):
if ',' in option:
ips = option.split(',')
return ips
elif '-' in option:
ip_start, ip_end = option.split('-')
ip_net = '.'.join(ip_start.split('.')[:-1])
start = int(ip_start.split('.')[-1])
end = int(ip_end.split('.')[-1]) + 1
ips = [ip_net + '.' + str(i) for i in range(start, end)]
return ips
elif ',' not in option or '-' not in option:
ips = [option]
return ips
else:
print("{0} -h".format(__file__))

def ssh_conn(ip, cmd):
ssh = paramiko.SSHClient() # 创建链接对象
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 指定当对方主机没有本机公钥的情况时应该怎么办,AutoAddPolicy表示自动在对方主机保存>下本机的秘钥
pkey_file = '/root/.ssh/id_rsa' # 指定私钥位置
key = paramiko.RSAKey.from_private_key_file(pkey_file, password='123456') # 创建秘钥链接对象,密码为创建秘钥时设置的,没有设置就留空
try:
ssh.connect(hostname=ip, username='root', pkey=key, timeout=1)
except:
print("Timeout or not parmission")
return 1
stdin, stdout, stderr = ssh.exec_command(cmd) # 输出会分别保存到三个文件里
stdout = stdout.read()[:-1] # [:-1]在这里的作用是去掉最后一个字符,因为这个最后输出会有个换行符
stderr = stderr.read()[:-1]
if stdout:
print("{0}: {1}".format(ip, stdout))
ssh.close()
else:
print("{0}: {1}".format(ip, stderr))
ssh.close()


if __name__ == '__main__':
paramiko.util.log_to_file('/root/python/paramikos/paramiko.log') # 输出日志
options, args = opt()
try:
cmd = args[0]
except:
print("{0} follow a command".format(__file__))
sys.exit(1)
if options.addr:
ips = parseOpt(options.addr)
else:
print("{0} -h".format(__file__))
sys.exit(1)
pool = multiprocessing.Pool(processes=10) #开启10个进程池
for ip in ips:
pool.apply_async(func=ssh_conn, args=(ip, cmd)) #异步进程
pool.close()
pool.join() #阻塞主进程

 

posted @ 2018-05-31 19:58  一条咸鱼的梦想  阅读(204)  评论(0编辑  收藏  举报