1*061da546Spatrickimport sys 2*061da546Spatrickimport types 3*061da546Spatrick 4*061da546Spatrickfrom .exceptions import EOF, TIMEOUT 5*061da546Spatrickfrom .pty_spawn import spawn 6*061da546Spatrick 7*061da546Spatrickdef run(command, timeout=30, withexitstatus=False, events=None, 8*061da546Spatrick extra_args=None, logfile=None, cwd=None, env=None, **kwargs): 9*061da546Spatrick 10*061da546Spatrick ''' 11*061da546Spatrick This function runs the given command; waits for it to finish; then 12*061da546Spatrick returns all output as a string. STDERR is included in output. If the full 13*061da546Spatrick path to the command is not given then the path is searched. 14*061da546Spatrick 15*061da546Spatrick Note that lines are terminated by CR/LF (\\r\\n) combination even on 16*061da546Spatrick UNIX-like systems because this is the standard for pseudottys. If you set 17*061da546Spatrick 'withexitstatus' to true, then run will return a tuple of (command_output, 18*061da546Spatrick exitstatus). If 'withexitstatus' is false then this returns just 19*061da546Spatrick command_output. 20*061da546Spatrick 21*061da546Spatrick The run() function can often be used instead of creating a spawn instance. 22*061da546Spatrick For example, the following code uses spawn:: 23*061da546Spatrick 24*061da546Spatrick from pexpect import * 25*061da546Spatrick child = spawn('scp foo user@example.com:.') 26*061da546Spatrick child.expect('(?i)password') 27*061da546Spatrick child.sendline(mypassword) 28*061da546Spatrick 29*061da546Spatrick The previous code can be replace with the following:: 30*061da546Spatrick 31*061da546Spatrick from pexpect import * 32*061da546Spatrick run('scp foo user@example.com:.', events={'(?i)password': mypassword}) 33*061da546Spatrick 34*061da546Spatrick **Examples** 35*061da546Spatrick 36*061da546Spatrick Start the apache daemon on the local machine:: 37*061da546Spatrick 38*061da546Spatrick from pexpect import * 39*061da546Spatrick run("/usr/local/apache/bin/apachectl start") 40*061da546Spatrick 41*061da546Spatrick Check in a file using SVN:: 42*061da546Spatrick 43*061da546Spatrick from pexpect import * 44*061da546Spatrick run("svn ci -m 'automatic commit' my_file.py") 45*061da546Spatrick 46*061da546Spatrick Run a command and capture exit status:: 47*061da546Spatrick 48*061da546Spatrick from pexpect import * 49*061da546Spatrick (command_output, exitstatus) = run('ls -l /bin', withexitstatus=1) 50*061da546Spatrick 51*061da546Spatrick The following will run SSH and execute 'ls -l' on the remote machine. The 52*061da546Spatrick password 'secret' will be sent if the '(?i)password' pattern is ever seen:: 53*061da546Spatrick 54*061da546Spatrick run("ssh username@machine.example.com 'ls -l'", 55*061da546Spatrick events={'(?i)password':'secret\\n'}) 56*061da546Spatrick 57*061da546Spatrick This will start mencoder to rip a video from DVD. This will also display 58*061da546Spatrick progress ticks every 5 seconds as it runs. For example:: 59*061da546Spatrick 60*061da546Spatrick from pexpect import * 61*061da546Spatrick def print_ticks(d): 62*061da546Spatrick print d['event_count'], 63*061da546Spatrick run("mencoder dvd://1 -o video.avi -oac copy -ovc copy", 64*061da546Spatrick events={TIMEOUT:print_ticks}, timeout=5) 65*061da546Spatrick 66*061da546Spatrick The 'events' argument should be either a dictionary or a tuple list that 67*061da546Spatrick contains patterns and responses. Whenever one of the patterns is seen 68*061da546Spatrick in the command output, run() will send the associated response string. 69*061da546Spatrick So, run() in the above example can be also written as: 70*061da546Spatrick 71*061da546Spatrick run("mencoder dvd://1 -o video.avi -oac copy -ovc copy", 72*061da546Spatrick events=[(TIMEOUT,print_ticks)], timeout=5) 73*061da546Spatrick 74*061da546Spatrick Use a tuple list for events if the command output requires a delicate 75*061da546Spatrick control over what pattern should be matched, since the tuple list is passed 76*061da546Spatrick to pexpect() as its pattern list, with the order of patterns preserved. 77*061da546Spatrick 78*061da546Spatrick Note that you should put newlines in your string if Enter is necessary. 79*061da546Spatrick 80*061da546Spatrick Like the example above, the responses may also contain a callback, either 81*061da546Spatrick a function or method. It should accept a dictionary value as an argument. 82*061da546Spatrick The dictionary contains all the locals from the run() function, so you can 83*061da546Spatrick access the child spawn object or any other variable defined in run() 84*061da546Spatrick (event_count, child, and extra_args are the most useful). A callback may 85*061da546Spatrick return True to stop the current run process. Otherwise run() continues 86*061da546Spatrick until the next event. A callback may also return a string which will be 87*061da546Spatrick sent to the child. 'extra_args' is not used by directly run(). It provides 88*061da546Spatrick a way to pass data to a callback function through run() through the locals 89*061da546Spatrick dictionary passed to a callback. 90*061da546Spatrick 91*061da546Spatrick Like :class:`spawn`, passing *encoding* will make it work with unicode 92*061da546Spatrick instead of bytes. You can pass *codec_errors* to control how errors in 93*061da546Spatrick encoding and decoding are handled. 94*061da546Spatrick ''' 95*061da546Spatrick if timeout == -1: 96*061da546Spatrick child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env, 97*061da546Spatrick **kwargs) 98*061da546Spatrick else: 99*061da546Spatrick child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile, 100*061da546Spatrick cwd=cwd, env=env, **kwargs) 101*061da546Spatrick if isinstance(events, list): 102*061da546Spatrick patterns= [x for x,y in events] 103*061da546Spatrick responses = [y for x,y in events] 104*061da546Spatrick elif isinstance(events, dict): 105*061da546Spatrick patterns = list(events.keys()) 106*061da546Spatrick responses = list(events.values()) 107*061da546Spatrick else: 108*061da546Spatrick # This assumes EOF or TIMEOUT will eventually cause run to terminate. 109*061da546Spatrick patterns = None 110*061da546Spatrick responses = None 111*061da546Spatrick child_result_list = [] 112*061da546Spatrick event_count = 0 113*061da546Spatrick while True: 114*061da546Spatrick try: 115*061da546Spatrick index = child.expect(patterns) 116*061da546Spatrick if isinstance(child.after, child.allowed_string_types): 117*061da546Spatrick child_result_list.append(child.before + child.after) 118*061da546Spatrick else: 119*061da546Spatrick # child.after may have been a TIMEOUT or EOF, 120*061da546Spatrick # which we don't want appended to the list. 121*061da546Spatrick child_result_list.append(child.before) 122*061da546Spatrick if isinstance(responses[index], child.allowed_string_types): 123*061da546Spatrick child.send(responses[index]) 124*061da546Spatrick elif (isinstance(responses[index], types.FunctionType) or 125*061da546Spatrick isinstance(responses[index], types.MethodType)): 126*061da546Spatrick callback_result = responses[index](locals()) 127*061da546Spatrick sys.stdout.flush() 128*061da546Spatrick if isinstance(callback_result, child.allowed_string_types): 129*061da546Spatrick child.send(callback_result) 130*061da546Spatrick elif callback_result: 131*061da546Spatrick break 132*061da546Spatrick else: 133*061da546Spatrick raise TypeError("parameter `event' at index {index} must be " 134*061da546Spatrick "a string, method, or function: {value!r}" 135*061da546Spatrick .format(index=index, value=responses[index])) 136*061da546Spatrick event_count = event_count + 1 137*061da546Spatrick except TIMEOUT: 138*061da546Spatrick child_result_list.append(child.before) 139*061da546Spatrick break 140*061da546Spatrick except EOF: 141*061da546Spatrick child_result_list.append(child.before) 142*061da546Spatrick break 143*061da546Spatrick child_result = child.string_type().join(child_result_list) 144*061da546Spatrick if withexitstatus: 145*061da546Spatrick child.close() 146*061da546Spatrick return (child_result, child.exitstatus) 147*061da546Spatrick else: 148*061da546Spatrick return child_result 149*061da546Spatrick 150*061da546Spatrickdef runu(command, timeout=30, withexitstatus=False, events=None, 151*061da546Spatrick extra_args=None, logfile=None, cwd=None, env=None, **kwargs): 152*061da546Spatrick """Deprecated: pass encoding to run() instead. 153*061da546Spatrick """ 154*061da546Spatrick kwargs.setdefault('encoding', 'utf-8') 155*061da546Spatrick return run(command, timeout=timeout, withexitstatus=withexitstatus, 156*061da546Spatrick events=events, extra_args=extra_args, logfile=logfile, cwd=cwd, 157*061da546Spatrick env=env, **kwargs) 158