要求安装了pexpect这个包先。
用法见usage:
Usage: ./multissh.py -f cmdfile -l username -c cmd -n nodesfile -v -r
execut cmd on remote hosts (all hosts in ./hosts.txt by default)
-v verbose
-r recording hosts on which mission succeeded and failed
-l username
-c cmd to be executed remotely
-n file containing the nodes
-f file conaining the cmd
-h show the usage
就是指定一个文件比如nodes.txt以及命令以后,它可以自动登录到nodes.txt包含的节点里执行命令。可以在源文件里替换进你自己的密码,也可以使用公钥密钥登录不需输入密码。指定了v选项的话得到在远端每台主机上的详细输出。指定了r选项的话记录下那些节点成功那些节点失败。
我前面的帖子里有关于ansi_color的一个脚本,拿过来可以配合使用得到彩色输出
使用前可能要根据情况修改prompt变量的定义. 这个变量是关于登录后提示符的正则表达.我根据我自己的几台机器随便写了两个.未必符合你的情况.
#!/usr/bin/python
import sys
import os
import getopt
import pexpect
import re
try:
from ansi_color import *
except ImportError:
def color_str(s, *args):
return s
fg_green = None
fg_red = None
fg_blue = None
prompt = "^.*\(.*\):|\[.*@.*\]|\$"
nl = open("/dev/null", "w")
def _print(s):
if not single_mode:
print s
def do(cmds, hostname, username):
global verbose, quiet, good_hosts
#print "executing \"%s\""%(repr(cmds))
ret = 0
try:
sshcmd = 'ssh %s'%(hostname)
if username != None:
sshcmd = sshcmd + " -l %s"%username
s = pexpect.spawn(command=sshcmd, timeout=20)
if verbose:
s.logfile_read = sys.stdout
s.setecho(False)
else:
s.logfile_read = s.logfile_send = nl
s.setecho(False)
t = 0
while t < 3:
i = s.expect([prompt, pexpect.EOF, pexpect.TIMEOUT,\
"Are you sure you want to continue connecting (yes/no)?",\
"(P|p)assword:"])
t += 1
if i == 0:
break
elif i == 1:
_print("End Of File")
return 1
elif i == 2:
_print("time out")
return 1
elif i == 3:
s.sendline("yes")
elif i == 4:
s.sendline(password)
if t >= 3:
return 1
if cmds:
for cmd in cmds:
s.sendline(cmd)
s.expect(prompt)
else:
_print("\nEntering interactive mode, please ^] to escape")
s.interact()
s.sendline("exit")
s.close()
return 0
except pexpect.ExceptionPexpect:
return 1
def print_usage():
print "Usage:\t ./multissh.py -f cmdfile -l username -c cmd -n nodesfile -v -r"
print "execut cmd on remote hosts (all hosts in ./hosts.txt by default)"
print "\t-v verbose"
print "\t-r recording hosts on which mission succeeded and failed"
print "\t-l username"
print "\t-c cmd to be executed remotely"
print "\t-n file containing the nodes"
print "\t-f file conaining the cmd"
print "\t-h show the usage"
print "\t-p password"
sys.exit(0)
if __name__ == "__main__":
try:
opts, args=getopt.getopt(sys.argv[1:], \
"l:f:n:c:p:vhrq",["login_name", "cmdfile","nodesfile","command","password","verbose","help","recording","quiet"])
except getopt.GetoptError, err:
print str(err)
print_usage()
if opts == [] and args == []:
print_usage()
if args:
hosts = [args[0]]
else:
hosts = []
cmds = []
verbose = False
quiet = False
username = None
recording = False
password = ""
single_mode = True
for o, ra in opts:
a = ra.strip("\n")
if o in ("-h", "--help"):
print_usage()
elif o in ("-n", "--nodesfile"):
hosts = [l.strip(" \t\n") for l in open(a, 'r')]
single_mode = False
elif o in ("-c", "--command"):
cmds = [a]
elif o in ("-f", "--cmdfile"):
cmds = [cmd.strip(' \n') for cmd in open(a, 'r')]
elif o in ("-v", "--verbose"):
verbose = True
elif o in ("-q", "--quiet"):
quiet = True
elif o in ("-r", "--recording"):
recording = True
elif o in ("-l", "--login_name"):
username = a
elif o in ("-p", "--password"):
password = a
if not hosts:
_print("using default ./hosts.txt")
h = open(os.path.join(os.path.expanduser("."), "hosts.txt"),'r')
hosts = [dst.strip(' \n') for dst in h]
if recording:
f_good = open("good_hosts.txt","w")
f_bad = open("bad_hosts.txt","w")
good_hosts =[]
bad_hosts =[]
for (i, hostname) in enumerate(hosts):
_print ("%d/%d: ["%(i+1, len(hosts))+ color_str(hostname, fg_blue)+"]")
ret = do(cmds, hostname, username)
if verbose:
print
if ret == 1:
bad_hosts.append(hostname)
_print("["+color_str("Fail!", fg_red)+"]")
if recording:
print>>f_bad, hostname
f_bad.flush()
else:
good_hosts.append(hostname)
_print ("["+color_str("OK!", fg_green)+"]")
if recording:
print>>f_good, hostname
f_good.flush()
_print ("%d hosts suceed!"%len(good_hosts))
sys.exit(ret)