Skip to content

Instantly share code, notes, and snippets.

@wenLiangcan
Forked from zhangchunlin/prun
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wenLiangcan/decf54374bbfd905bc53 to your computer and use it in GitHub Desktop.
Save wenLiangcan/decf54374bbfd905bc53 to your computer and use it in GitHub Desktop.
#! /usr/bin/env python
#coding=utf-8
import gevent
from gevent.subprocess import Popen, PIPE
import sys
def run(cmd,name="",index=1,color=True):
fc = 32 + index%5
if name:
if color:
name = "\033[%dm%s\033[0m"%(fc,name)
sub = Popen([cmd], stdout=PIPE, stderr=PIPE, shell=True)
def print_stdout():
for l in sub.stdout:
print "%s: %s"%(name,l),
def print_stderr():
for l in sub.stderr:
if color:
l = "\033[31m%s\033[0m"%(l)
print >> sys.stderr,"%s: %s"%(name,l)
g1 = gevent.spawn(print_stdout)
g2 = gevent.spawn(print_stderr)
sub.wait()
g1.kill()
g2.kill()
end_str = "--- end ---"
if color:
end = "%s: \033[31m%s\033[0m"%(name,end_str)
else:
end = "%s: %s"%(name,end_str)
print end
return sub.returncode
def prun(cmds,color=True):
def get_name_cmd(cmd,index):
if type(cmd)==type(""):
name = "cmd%d"%(index)
cmd2 = cmd
else:
name,cmd2 = cmd
return name,cmd2
l = []
for index,cmd in enumerate(cmds):
name,cmd2 = get_name_cmd(cmd,index+1)
fc = 32 + index%5
if color:
name2 = "\033[%dm%s\033[0m"%(fc,name)
else:
name2 = name
print "%s %s: %s"%(index+1,name2,cmd2)
g = gevent.spawn(run,cmd=cmd2,name=name,index=index,color=color)
l.append(g)
print
gevent.joinall(l)
for index,g in enumerate(l):
if g.value!=0:
name,cmd2 = get_name_cmd(cmds[index],index+1)
errmsg = "error: '%s' return %s"%(cmd2,g.value)
if color:
errmsg = "\033[31m%s\033[0m"%(errmsg)
print
print >> sys.stderr,errmsg
sys.exit(g.value)
def main():
from optparse import OptionParser
parser = OptionParser()
usage = 'usage: %prog [options] "name1:cmd1" "name2:cmd2"...'
parser.set_usage(usage)
parser.add_option('--no-color', dest='no_color', default=False, help="no color when print stdio", action='store_true')
options, args = parser.parse_args()
def cmdsplit(cmd):
l = cmd.split(":")
if len(l)>1:
return l[0],":".join(l[1:])
return cmd
cmds = map(cmdsplit,args)
if cmds:
prun(cmds, not options.no_color)
else:
parser.print_help()
if __name__ == '__main__':
main()
#!/usr/bin/env python3
"""
Port of prun to Python 3.
"""
import sys
from concurrent import futures
from concurrent.futures import ThreadPoolExecutor
from subprocess import PIPE, Popen
RED = 31
def colored(text, auto=0, value=0, enable=True):
template = '\033[%dm%s\033[0m'
if enable:
if auto:
return template % (32 + (auto-1) % 5, text)
elif value:
return template % (value, text)
else:
return text
def run(cmd, name='', index=1, color=True):
def print_stdout(process, name):
for l in process.stdout:
print("{}: {}".format(name, l.decode('utf-8')), end='')
def print_stderr(process):
for l in process.stderr:
print(
"{}: {}".format(
name,
colored(l.decode('utf-8'), value=RED, enable=color)),
file=sys.stderr
)
name = colored(name, index, enable=color)
sub = Popen([cmd], stdout=PIPE, stderr=PIPE, shell=True)
with ThreadPoolExecutor(2) as executor:
executor.submit(print_stdout, sub, name)
executor.submit(print_stderr, sub)
end_str = '--- end ---'
end = '%s: %s' % (name, colored(end_str, value=RED, enable=color))
print(end)
return sub.returncode
def prun(cmds, color=True):
executor = ThreadPoolExecutor(len(cmds))
Futures = []
for index, item in enumerate(cmds):
name, cmd = item
print('{} {}: {}'.format(
index+1, colored(name, auto=index+1, enable=color), cmd))
f = executor.submit(
run, cmd=cmd, name=name, index=index+1, color=color)
Futures.append(f)
print()
futures.wait(Futures)
for index, f in enumerate(Futures):
if f.result():
cmd = cmds[index][1]
errmsg = colored(
'error: "%s" return %s' % (cmd, f.result()),
value=RED,
enable=color)
print()
print(errmsg, file=sys.stderr)
sys.exit(f.result())
def main():
import argparse
argparser = argparse.ArgumentParser(
description='Run system commands concurrently.',
usage='%(prog)s [options] "name1:cmd1" "name2:cmd2"...'
)
argparser.add_argument('cmds',
metavar='<command>',
nargs='+',
help='system command')
argparser.add_argument('--no-color',
dest='no_color',
help='turn output highlighting off',
action='store_true')
args = argparser.parse_args()
def gencmd(index, string):
l = string.split(':')
if len(l) == 1:
return 'cmd%d' % index, l[0]
return l[0], ":".join(l[1:])
cmds = [
gencmd(index+1, s)
for index, s in enumerate(args.cmds)
]
prun(cmds, not args.no_color)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment