Esse script possibilita a execução de comandos remotamente utilizando o protocolo SSH. Os comandos podem ser executados individualmente ou em lote para um ou mais servidores.
O script foi desenvolvido em Python para Windows e utilizando paramiko e pycrypto para instalar o SSH nesse sistema. As versões citadas no READ-ME abaixo certamente estão desatualizadas. Para executar a partir de uma máquina Linux não deve ter qualquer problema.
READ.ME
bssh - ver. 0.3 Bulk SSH (bssh) is a python script written to provide remote command submission to one or more servers/hosts using ssh protocol. Written to run on Win32 environment, should run on Linux with minor or no modification. VERSION HISTORY: 0.1: Simple command execution 0.2: Support to input response to programs running on remote host. 0.3: Added username and password parameters. INSTALATION: Download and run the following installers: http://www.python.org/ftp/python/2.7.1/python-2.7.1.msi http://bialix.com/python/paramiko-1.7.3-ctypes.win32.exe http://www.serenethinking.com/bitlift/tl_files/pycrypto-2.3.win32-py2.7.msi USAGE: bssh <options> OPTIONS: -h, --help Show this help. -d, --debug Show debug messages. -c, --command=<command> Single command to be executed on remote server. -f, --commandfile=<command file name> Name of the file containing all commands that will run on remote server. (See below for details) -s, --server=<server name> Single target server name or IP address. -l, --serverlist=<server list file name> Name of the file containing all target servers names or IP address, one per line. -o, --output=<file name> Sends output text to a file. -u, --username=<user id> User id to ssh sign-on. -p, --password=<password> User password to ssh sign-on. COMMAND FILE: Text file containing one command per line to be executed on the remote host/server. Each command is preceded of a meta command to be interpreted by bssh script as follows. Meta commands: $C <command> Executes a command on remote host and catches it's stdout $R <command> Run a program and feeds to it's prompts with "input text" ($I) provided right below. $I <input text> Text to be provided to programa executed with "run" ($R) command. For consecutive responses, use $I for each program prompt. # <comment> The trailing text will not be executed and will be considered as a comment. Additionaly to meta commands there are some meta data that can be used in a command line. Meta data: $user$ Replaced by username provided as credential to SSH login. $pass$ Replaced by password provided as credential to SSH authentication.
CÓDIGO
# # bssh - Bulk SSH # Description: Submit a single command or a command sequence to remote # host(s) using SSH protocol. # Author.....: Megumi K. Jr. # Date.......: Sep, 12 2011 # Version history: # 0.3: Added user and password parameter option # scriptname = "bssh" # Script Name scriptver = "0.3" # Version # import os, re, sys import string import getpass import getopt import time import paramiko from types import * # http://docs.python.org/library/types.html#module-types def main(): global username global password global debug command = None cmdfile = None server = None serverlist = None username = None password = None debug = False # Check if options were informed try: opts, args = getopt.getopt(sys.argv[1:], "hdc:f:s:l:o:u:p:", \ ["help", "debug", "command=", "commandfile=", "server=", "serverlist=", "output=", "username=", "password="]) except getopt.GetoptError, err: # print help information and exit: print str(err) print Usage() sys.exit(2) # Get all options for o, a in opts: if o in ("-h", "--help"): Usage() sys.exit() elif o in ("-d", "--debug"): debug = True elif o in ("-c", "--command"): command = a elif o in ("-f", "--commandfile"): cmdfile = a elif o in ("-s", "--server"): server = a elif o in ("-l", "--serverlist"): serverlist = a elif o in ("-o", "--output"): sys.stdout = Logger(a) elif o in ("-u", "--username"): username = a elif o in ("-p", "--password"): password = a else: Usage() sys.exit(2) # Check if is only one command to be executed if command != None: # only one command to be run cmd = command # var "cmd" will have the command else: if cmdfile != None: try: # var "cmd" will have file handler cmd = open(cmdfile) except IOError as e: print("{0}".format(e)) sys.exit(2) else: Usage() sys.exit(2) # Check if is only one server if server != None: # will run commands only on one server srv = server # var "srv" will have server name else: if serverlist != None: # Open server list file try: # var "srv" will have file handler srv = open(serverlist) except IOError as e: print("{0}".format(e)) sys.exit(2) else: Usage() sys.exit(2) # Get user credentials print print "%s - ver. %s" % (scriptname, scriptver) if username == None: print "Logon credentials" username = raw_input('Username: ') password = getpass.getpass("Password: ") ProcServer(srv, cmd) return # endDef def Usage(): try: helpfile = sys.path[0] + "\\READ.ME" help = open(helpfile) except IOError as e: print 'Error reading "%s" file.' % helpfile print("{0}".format(e)) sys.exit(2) help.close() cmd = 'more "%s"' % helpfile os.system(cmd) print sys.exit(0) # endDef def ProcServer(srv, cmd): # Process a server or servers list if type(srv) == StringType: # If srv is StringType, contains server name ProcCommand(srv, cmd) # proc single server else: for servername in srv.read().splitlines(): # loop into server file if servername.strip() == "": # Skip empty lines continue elif servername.strip()[0] == "#": # Skip comments continue else: ProcCommand(servername, cmd) #endDef def ProcCommand(srv, cmd): print print "Host: %s" % srv print "-----------------------------------------------------------------------" ssh = OpenConnection(srv) if type(cmd) == StringType: # If cmd is StringType, contains single command ExecCmd(ssh, cmd) else: cmd.seek(0) # Point to file beginning ParseCmdFile(ssh, cmd) #endDef def ParseCmdFile(ssh, cmd): cmdList = [] for command in cmd.read().splitlines(): # Ignore empty lines or comments if command.strip() == "": # Skip empty lines continue elif command.strip()[0] == "#": # Skip comments continue command = NormalizeString(command) if command.strip()[:2].upper() == "$C": if len(cmdList) > 0: # If there's a pending program ExecCmd(ssh, cmdList) # execution, do it before cmdList = [] # the next command. command = command[2:].strip() ExecCmd(ssh, command) elif command.strip()[:2].upper() == "$R"\ or command.strip()[:2].upper() == "$I": cmdList.append(command[2:].strip()) continue if len(cmdList) > 0: # If there's a pending program ExecCmd(ssh, cmdList) # execution, do it before exit return # endDef def OpenConnection(server): if debug: # Turn on debug messages paramiko.common.logging.basicConfig(level=paramiko.common.DEBUG) ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: ssh.connect(server, username=username, password=password) except Exception, e: print("({0})".format(e)) sys.exit(2) return ssh # endDef def ExecCmd(ssh, command): if type(command) == ListType: # If it is a list of commands cmd = command[0] # get 1st cmd. else: cmd = command print "$> %s" % (cmd) stdin, stdout, stderr = ssh.exec_command(cmd) if type(command) == ListType: # If it is a list of commands for cmd in command[1:]: # continue sending next on stdin.write(cmd+"\n") # the list stdin.flush() stdin.close() for line in stdout.read().splitlines(): print line print return stdout, stderr # endDef def NormalizeString(string): string = re.sub(r'(\$user\$)', username, string) # Replace meta var "username" string = re.sub(r'(\$pass\$)', password, string) # Replace meta var "password" # Removes/fixes leading/trailing newlines/whitespace and escapes double quotes with double quotes string = re.sub(r'(\r\n|\r|\n)', '\n', string) # Convert all newlines to unix newlines string = string.strip() # Remove leading/trailing whitespace/blank lines # string = re.sub(r'(")', '""', string) # Convert double quotes to double double quotes (e.g. 'foo "bar" blah' becomes 'foo ""bar"" blah') return string # endDef class Logger(object): # Duplicate "print" output to a file. def __init__(self, object): self.terminal = sys.stdout self.log = open(object, "a") def write(self, message): self.terminal.write(message) self.log.write(message) if __name__ == "__main__": main()
ARQUIVO DE COMANDOS (exemplo)
# Ver 0.3 Command File $C hostname $C date
ARQUIVO DE SERVIDORES (exemplo)
# Host name or ip address qaectlvbosapp503