Advertisement
cmiN

run

Jun 26th, 2012
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.94 KB | None | 0 0
  1. #! /usr/bin/env python
  2. # Shell Multi Runner
  3. # 12.02.2012 cmiN
  4. #
  5. # Execute commands in terminal asynchronously using subprocess
  6. # and show all output merged into one console.
  7. #
  8. # Contact: cmin764@yahoo/gmail.com
  9.  
  10.  
  11. import subprocess # better than popen/system/respawn
  12. from sys import argv, stdout
  13. from time import sleep
  14. from threading import active_count, Thread # parallelism
  15.  
  16.  
  17. # some settings
  18. FILE = None     # output to file too
  19. THRD = 10       # threads
  20. DLAY = 1        # delay
  21. CHAR = '@'      # wildcard
  22.  
  23.  
  24. # instantiated in only one object
  25. class Show(file):
  26.     """
  27.    Thread safe printing class.
  28.    Uses primitive locks.
  29.    """
  30.  
  31.     def __init__(self, fname=None):
  32.         """ If `fname` isn't `None` write output to file too. """
  33.         self.locked = False # unlocked
  34.         self.open_file(fname)
  35.  
  36.     def __del__(self):
  37.         """ Destructor. Close an opened file. """
  38.         if self.fname:
  39.             self.close()
  40.  
  41.     def open_file(self, fname):
  42.         """ Open file for writing. """
  43.         self.fname = fname
  44.         if fname: # init file
  45.             super(Show, self).__init__(fname, 'w')
  46.  
  47.     def write(self, data):
  48.         """ Safe write. """
  49.         while self.locked: # if writing in progress
  50.             pass # wait
  51.         # lock
  52.         self.locked = True
  53.         # write data
  54.         if self.fname:
  55.             super(Show, self).write(data)
  56.         stdout.write(data)
  57.         # flush data
  58.         if self.fname:
  59.             self.flush()
  60.         stdout.flush()
  61.         # release
  62.         self.locked = False
  63.  
  64.     def fileno(self):
  65.         """ Experimental. Used as file descriptor replacing pipes. """
  66.         if self.fname:
  67.             return super(Show, self).fileno()
  68.         return stdout.fileno()
  69.  
  70.  
  71. class Engine(Thread):
  72.     """
  73.    Execute each command in a separate thread
  74.    and listen for its output.
  75.    """
  76.  
  77.     def __init__(self, command):
  78.         super(Engine, self).__init__() # superclass constructor
  79.         self.command = command
  80.  
  81.     def run(self):
  82.         """ Function called from outside by `start` method. """
  83.         # fork the fucking process
  84.         pobj = subprocess.Popen(self.command.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  85.         # listen for new input
  86.         while True:
  87.             line = pobj.stdout.readline()
  88.             if line == "": # more output it's about to come
  89.                 if pobj.poll() != None: # nope
  90.                     break # so exit
  91.                 continue # try again
  92.             report.write(line)
  93.  
  94.  
  95. # globals
  96. usage = """
  97. Usage: {0} [options] command
  98.  
  99. Options:
  100.    -t, --threads <int>        how many asynchronous threads to run
  101.    -d, --delay <float>        time in seconds to wait between each run
  102.    -f, --file <str>           write output to file too
  103.  
  104. Commands:
  105.    <any valid command>        ex: wget {1}links.txt
  106.  
  107. If you preceed a parameter with {1} it becomes a list with parameters
  108. taken from a file called like itself.
  109. Old: ./scan -h 91.202.91.119 -u usr.txt -p pwd.txt
  110. New: {0} ./scan -h {1}hosts.txt -u usr.txt -p pwd.txt
  111. """.format(argv[0], CHAR)
  112. report = Show() # make verbose object
  113.  
  114.  
  115. def generate(command, expand, pos):
  116.     """ Format command recursively. """
  117.     if pos == len(expand):
  118.         # now command string is complete
  119.         sleep(DLAY) # delay
  120.         while active_count() > THRD:
  121.             pass # wait if number of threads is exceeded
  122.         report.write("[+] Start: %s\n" % command)
  123.         Engine(command).start()
  124.         return
  125.     expand[pos].seek(0) # rewind
  126.     for line in expand[pos]:
  127.         generate(command.replace("{%d}" % pos, line.strip()), expand, pos + 1)
  128.  
  129.  
  130. def main():
  131.     global FILE, THRD, DLAY, CHAR
  132.     # check
  133.     if len(argv) == 1 or argv[1] in ('-h', "--help"):
  134.         print usage
  135.         return # insuficient parameters
  136.     # parse
  137.     report.write("[+] Parsing...\n")
  138.     argv.pop(0) # remove script name
  139.     command = ""
  140.     ind = 0 # index
  141.     expand = [] # list with special parameters
  142.     while ind < len(argv):
  143.         if argv[ind] in ('-t', "--threads"):
  144.             ind += 1
  145.             THRD = int(argv[ind])
  146.         elif argv[ind] in ('-d', "--delay"):
  147.             ind += 1
  148.             DLAY = float(argv[ind])
  149.         elif argv[ind] in ('-f', "--file"):
  150.             ind += 1
  151.             FILE = argv[ind]
  152.             report.open_file(FILE)
  153.         elif argv[ind][0] == CHAR:
  154.             # reserve variable parameter for special ones
  155.             command += ' ' + "{%d}" % (len(expand))
  156.             # add to list special parameters (`CHAR`<smth>)
  157.             expand.append(open(argv[ind][1:], 'r')) # file objects
  158.         else:
  159.             command += ' ' + argv[ind]
  160.         ind += 1
  161.     # process
  162.     report.write("[+] Processing...\n")
  163.     generate(command.strip(), expand, 0)
  164.     while active_count() > 1:
  165.         pass # wait for running threads
  166.     report.write("[+] Done.\n")
  167.  
  168.  
  169. if __name__ == "__main__":
  170.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement