Credit: Jeff Bauer 13.7.1 ProblemYou need to send commands to one or more logins that can be on the local machine or on a remote machine, and the Telnet protocol is acceptable. 13.7.2 SolutionTelnet is one of the oldest protocols in the TCP/IP stack, but it may still be serviceable (at least within an intranet that is well-protected against sniffing and spoofing attacks). In any case, Python's standard module telnetlib supports Telnet quite well: # auto_telnet.py - remote control via telnet import os, sys, string, telnetlib from getpass import getpass class AutoTelnet: def _ _init_ _(self, user_list, cmd_list, **kw): self.host = kw.get('host', 'localhost') self.timeout = kw.get('timeout', 600) self.command_prompt = kw.get('command_prompt', "$ ") self.passwd = {} for user in user_list: self.passwd[user] = getpass("Enter user '%s' password: " % user) self.telnet = telnetlib.Telnet( ) for user in user_list: self.telnet.open(self.host) ok = self.action(user, cmd_list) if not ok: print "Unable to process:", user self.telnet.close( ) def action(self, user, cmd_list): t = self.telnet t.write("\n") login_prompt = "login: " response = t.read_until(login_prompt, 5) if string.count(response, login_prompt): print response else: return 0 t.write("%s\n" % user) password_prompt = "Password:" response = t.read_until(password_prompt, 3) if string.count(response, password_prompt): print response else: return 0 t.write("%s\n" % self.passwd[user]) response = t.read_until(self.command_prompt, 5) if not string.count(response, self.command_prompt): return 0 for cmd in cmd_list: t.write("%s\n" % cmd) response = t.read_until(self.command_prompt, self.timeout) if not string.count(response, self.command_prompt): return 0 print response return 1 if _ _name_ _ == '_ _main_ _': basename = os.path.splitext(os.path.basename(sys.argv[0]))[0] logname = os.environ.get("LOGNAME", os.environ.get("USERNAME")) host = 'localhost' import getopt optlist, user_list = getopt.getopt(sys.argv[1:], 'c:f:h:') usage = """ usage: %s [-h host] [-f cmdfile] [-c "command"] user1 user2 ... -c command -f command file -h host (default: '%s') Example: %s -c "echo $HOME" %s """ % (basename, host, basename, logname) if len(sys.argv) < 2: print usage sys.exit(1) cmd_list = [] for opt, optarg in optlist: if opt == '-f': for r in open(optarg).readlines( ): if string.rstrip(r): cmd_list.append(r) elif opt == '-c': command = optarg if command[0] == '"' and command[-1] == '"': command = command[1:-1] cmd_list.append(command) elif opt == '-h': host = optarg autoTelnet = AutoTelnet(user_list, cmd_list, host=host) 13.7.3 DiscussionPython's telnetlib lets you easily automate access to Telnet servers, even from non-Unix machines. As a flexible alternative to the popen functions, telnetlib is a handy technique to have in your system-administration toolbox. Generally, production code will be more robust, but this recipe should be enough to get you started in the right direction. The recipe's AutoTelnet class instantiates a single telnetlib.Telnet object that it uses in a loop over a list of users. For each user, it calls the open method of the Telnet instance to open the connection to the specified host, runs a series of commands in AutoTelnet's action method, and finally calls the close method of the Telnet instance to terminate the connection. AutoTelnet's action method is where the action is. All operations depend on two methods of the Telnet instance. The write method takes a single string argument and writes it to the connection. The t.read_until method takes two arguments, a string to wait for and a timeout in seconds, and returns a string with all the characters received from the connection until the timeout elapsed or the waited-for string occurred. action's code uses these two methods to wait for a login prompt and send the username; wait for a password prompt and send the password; and, repeatedly, wait for a command prompt (typically from a Unix shell at the other end of the connection) and send the commands in the list sequentially. One warning (which applies to Telnet and other old protocols): except, perhaps, for the transmission of completely public data not protected by a password that might be of interest to intruders of ill will, do not run Telnet (or nonanonymous FTP) on networks on which you are not completely sure that nobody is packet-sniffing, since these protocols date from an older, more trusting age. They let passwords, and everything else, travel in the clear, open to any snooper. This is not Python-specific. Whether you use Python or not, be advised: if there is any risk that somebody might be packet-sniffing, use ssh instead, so no password travels on the network in the clear, and the connection stream itself is encrypted. 13.7.4 See AlsoDocumentation on the standard library module telnetlib in the Library Reference. |