1#!/usr/bin/env python 2 3"""This spawns a sub-shell (bash) and gives the user interactive control. The 4entire shell session is logged to a file called script.log. This behaves much 5like the classic BSD command 'script'. 6 7./script.py [-a] [-c command] {logfilename} 8 9 logfilename : This is the name of the log file. Default is script.log. 10 -a : Append to log file. Default is to overwrite log file. 11 -c : spawn command. Default is to spawn the sh shell. 12 13Example: 14 15 This will start a bash shell and append to the log named my_session.log: 16 17 ./script.py -a -c bash my_session.log 18 19""" 20 21import os, sys, time, getopt 22import signal, fcntl, termios, struct 23import traceback 24import pexpect 25 26global_pexpect_instance = None # Used by signal handler 27 28def exit_with_usage(): 29 30 print globals()['__doc__'] 31 os._exit(1) 32 33def main(): 34 35 ###################################################################### 36 # Parse the options, arguments, get ready, etc. 37 ###################################################################### 38 try: 39 optlist, args = getopt.getopt(sys.argv[1:], 'h?ac:', ['help','h','?']) 40 except Exception, e: 41 print str(e) 42 exit_with_usage() 43 options = dict(optlist) 44 if len(args) > 1: 45 exit_with_usage() 46 47 if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]: 48 print "Help:" 49 exit_with_usage() 50 51 if len(args) == 1: 52 script_filename = args[0] 53 else: 54 script_filename = "script.log" 55 if '-a' in options: 56 fout = file (script_filename, "ab") 57 else: 58 fout = file (script_filename, "wb") 59 if '-c' in options: 60 command = options['-c'] 61 else: 62 command = "sh" 63 64 # Begin log with date/time in the form CCCCyymm.hhmmss 65 fout.write ('# %4d%02d%02d.%02d%02d%02d \n' % time.localtime()[:-3]) 66 67 ###################################################################### 68 # Start the interactive session 69 ###################################################################### 70 p = pexpect.spawn(command) 71 p.logfile = fout 72 global global_pexpect_instance 73 global_pexpect_instance = p 74 signal.signal(signal.SIGWINCH, sigwinch_passthrough) 75 76 print "Script recording started. Type ^] (ASCII 29) to escape from the script shell." 77 p.interact(chr(29)) 78 fout.close() 79 return 0 80 81def sigwinch_passthrough (sig, data): 82 83 # Check for buggy platforms (see pexpect.setwinsize()). 84 if 'TIOCGWINSZ' in dir(termios): 85 TIOCGWINSZ = termios.TIOCGWINSZ 86 else: 87 TIOCGWINSZ = 1074295912 # assume 88 s = struct.pack ("HHHH", 0, 0, 0, 0) 89 a = struct.unpack ('HHHH', fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ , s)) 90 global global_pexpect_instance 91 global_pexpect_instance.setwinsize(a[0],a[1]) 92 93if __name__ == "__main__": 94 try: 95 main() 96 except SystemExit, e: 97 raise e 98 except Exception, e: 99 print "ERROR" 100 print str(e) 101 traceback.print_exc() 102 os._exit(1) 103 104