要求安装了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)