Skip to main content

Run commands simultaneously

Project description

multiCMD

A simple script that is able to issue multiple commands and execute them at the same time locally.

multiCMD can display realtime-ish outputs in color if running multiple commands at the same time.

It can be used in bash scripts for automation actions, and it can also be imported and act as a wrapper for subprocess.

  • Use return_object=True with run_commands or run_command to get the Task Object (definition below).
  • Use quiet=True and wait_for_return=False to create a daemon thread that asynchronously updates the return list / objects when commands finish.

For each process, a thread will be initialized if using -m/--max_threads > 1.
For each thread, subprocess is used to open a process for the command task.
Two additional threads are opened for processing input and output for the task.

The input / output threads are non-blocking.
Thus, using -t/--timeout will work more reliably.

Note: timeout specifies how many seconds multiCMD will wait before killing the command if no committed output was detected for this duration. An output line is considered committed if the stream handler encounters a \n or \r character.

Install via

pip install multiCMD

multiCMD will be available as

mcmd
multiCMD
multicmd
$ mcmd -h
usage: mcmd [-h] [-t timeout] [-m max_threads] [-q] [-V] command [command ...]

Run multiple commands in parallel

positional arguments:
  command               commands to run

options:
  -h, --help            show this help message and exit
  -p, --parse           Parse ranged input and expand them into multiple commands
  -t timeout, --timeout timeout
                        timeout for each command
  -m max_threads, --max_threads max_threads
                        maximum number of threads to use
  -q, --quiet           quiet mode
  -V, --version         show program's version number and exit
def run_commands(commands, timeout=0,max_threads=1,quiet=False,dry_run=False,with_stdErr=False,
				 return_code_only=False,return_object=False, parse = False, wait_for_return = True):
	'''
	Run multiple commands in parallel

	@params:
		commands: A list of commands to run ( list[str] | list[list[str]] )
		timeout: The timeout for each command
		max_threads: The maximum number of threads to use
		quiet: Whether to suppress output
		dry_run: Whether to simulate running the commands
		with_stdErr: Whether to append the standard error output to the standard output
		return_code_only: Whether to return only the return code
		return_object: Whether to return the Task object
		parse: Whether to parse ranged input
		wait_for_return: Whether to wait for the return of the commands

	@returns:
		list: The output of the commands ( list[None] | list[int] | list[list[str]] | list[Task] )
  '''
def run_command(command, timeout=0,max_threads=1,quiet=False,dry_run=False,with_stdErr=False,
				return_code_only=False,return_object=False,wait_for_return=True):
	'''
	Run a command

	@params:
		command: The command to run
		timeout: The timeout for the command
		max_threads: The maximum number of threads to use
		quiet: Whether to suppress output
		dry_run: Whether to simulate running the command
		with_stdErr: Whether to append the standard error output to the standard output
		return_code_only: Whether to return only the return code
		return_object: Whether to return the Task object
		wait_for_return: Whether to wait for the return of the command

	@returns:
		None | int | list[str] | Task: The output of the command
	'''
def join_threads(threads=__running_threads,timeout=None):
	'''
	Join threads

	@params:
		threads: The threads to join
		timeout: The timeout

	@returns:
		None
	'''
def input_with_timeout_and_countdown(timeout, prompt='Please enter your selection'):
	"""
	Read an input from the user with a timeout and a countdown.

	@params:
		timeout: The timeout in seconds
		prompt: The prompt to display to the user

	@returns:
		str: The input from the user or None if no input was received

	"""
def print_progress_bar(iteration, total, prefix='', suffix=''):
	'''
	Call in a loop to create terminal progress bar
	@params:
		iteration   - Required  : current iteration (Int)
		total       - Required  : total iterations (Int)
		prefix      - Optional  : prefix string (Str)
		suffix      - Optional  : suffix string (Str)

	@returns:
		None
	'''
def get_terminal_size():
	'''
	Get the terminal size

	@params:
		None

	@returns:
		(int,int): the number of columns and rows of the terminal
	'''
def int_to_color(n, brightness_threshold=500):
	'''
	Convert an integer to a color

	@params:
		n: The integer
		brightness_threshold: The brightness threshold

	@returns:
		(int,int,int): The RGB color
	'''
class Task:
	def __init__(self, command):
		self.command = command
		self.returncode = None
		self.stdout = []
		self.stderr = []

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

multicmd-1.41.tar.gz (13.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

multicmd-1.41-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

Details for the file multicmd-1.41.tar.gz.

File metadata

  • Download URL: multicmd-1.41.tar.gz
  • Upload date:
  • Size: 13.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.12 {"installer":{"name":"uv","version":"0.9.12"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"43","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for multicmd-1.41.tar.gz
Algorithm Hash digest
SHA256 d357a71beea76fac5d53cea3cf34556d91c076220259933adb1409468588705b
MD5 52b8d13679d2a223a89af23d2f11e5a1
BLAKE2b-256 92d56487231ed2ac7b8efcddcd0bc35da06f984fed87d61a912b4d8c7b503f33

See more details on using hashes here.

File details

Details for the file multicmd-1.41-py3-none-any.whl.

File metadata

  • Download URL: multicmd-1.41-py3-none-any.whl
  • Upload date:
  • Size: 13.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.12 {"installer":{"name":"uv","version":"0.9.12"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"43","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for multicmd-1.41-py3-none-any.whl
Algorithm Hash digest
SHA256 a161643541bb2068df59d1027831af776c60a6fd00cbc6fa30eb49ecd1a2942b
MD5 08fbbf9ba324129ca9f19d6ea9b7d529
BLAKE2b-256 8d9fc84c64bc7dcafa3a62b692c1b20577c807b2b7077d72050715a50a4d427c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page