Skip to content

Instantly share code, notes, and snippets.

@runekaagaard
Last active April 8, 2022 05:53
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 runekaagaard/197de9ba59c0c7532d9cff0c2d5cf259 to your computer and use it in GitHub Desktop.
Save runekaagaard/197de9ba59c0c7532d9cff0c2d5cf259 to your computer and use it in GitHub Desktop.
Runs and outputs multiple bash commands in one terminal. Each command gets a color. "pip install termcolor" is needed.
import fcntl, os, re, sys, signal
from subprocess import Popen, PIPE
from termcolor import colored
from itertools import cycle
RE = re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]')
CLEARLN = "\033[2K\r"
def escape_ansi(s):
return RE.sub('', s)
def nonblock(stream):
fcntl.fcntl(stream, fcntl.F_SETFL, fcntl.fcntl(stream, fcntl.F_GETFL) | os.O_NONBLOCK)
def popen(cmd):
return Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE, universal_newlines=True, executable='/bin/bash')
def output(proc, color):
for line in proc.stdout.readlines():
print(colored(escape_ansi(line), color), end="")
for line in proc.stderr.readlines():
print(colored(escape_ansi(line), "red"), end="")
def hr():
nonblock(sys.stdin)
for _ in sys.stdin.readlines():
print(colored("-" * os.get_terminal_size().columns, "white", "on_grey"), "\n", sep="")
def signal_handler(sig, frame):
print(CLEARLN, end="")
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
def main():
procs = [popen(x) for x in cmds]
for proc in procs:
nonblock(proc.stdout)
nonblock(proc.stderr)
while True:
for proc, color in zip(procs, cycle(colors)):
output(proc, color)
hr()
colors = ["white", "green", "yellow", "blue", "magenta", "cyan", "grey"]
cmds = [
"tail -f /var/log/foo",
"cd /project && runserver",
"date && sleep 5",
]
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment