zyongye/parallel-exec

★ 0Forks 0PythonGitHub ↗Compare

README

pexec

Execute the same command on multiple machines in parallel via SSH.

Install

# Make it executable and symlink to your PATH
chmod +x pexec
sudo ln -s $(pwd)/pexec /usr/local/bin/pexec

Usage

# Single command
pexec -H web1,web2,db1 "uptime"

# Multiple -H flags
pexec -H web1,web2 -H db1,db2 "df -h"

# With user
pexec -H root@web1,deploy@web2 "systemctl status nginx"

# From a hosts file (one host per line)
pexec -f hosts.txt "uname -r"

Session mode (preserving environment)

All -c commands run in a single shell session, so sourced environment variables, aliases, and working directory persist across commands:

# Source an env file, then use its variables
pexec -H web1,web2 -c "source /opt/app/env.sh" -c 'echo $APP_HOME' -c "run_app"

# Login shell (auto-sources ~/.bashrc, ~/.profile)
pexec -H web1,web2 --login -c "conda activate myenv" -c "python train.py"

# Execute a local script on remote hosts
pexec -H web1,web2 -s deploy.sh

# Setup env first, then run a script
pexec -H web1,web2 -c "source /opt/env.sh" -s deploy.sh

# Pipe commands from stdin
echo "uptime && df -h" | pexec -H web1,web2

YAML config file

Define hosts, commands, and settings in a YAML file instead of CLI flags:

pexec --config deploy.yaml
# deploy.yaml
hosts:
  - web1
  - web2
  - root@db1

commands:
  - source /opt/app/env.sh
  - echo $APP_HOME
  - systemctl restart myapp

parallel: 4
timeout: 60
login: true
stream: true
# identity: ~/.ssh/deploy_key
# port: 22
# user: deploy
# script: deploy.sh
# no_strict: false
# json: false

CLI flags override config values, so you can use a config as a base and tweak per-run:

# Use config but add an extra host and override parallelism
pexec --config deploy.yaml -H extra-host -p 2

Default config location: ~/.pexec.yaml (loaded automatically if it exists).

Other features

# Stream output in real-time (for long-running commands)
pexec -H web1,web2 --stream -c "source env.sh" -c "make build"

# JSON output (for scripting)
pexec -H web1,web2 --json "hostname"

# Limit parallelism
pexec -H host1,host2,host3,host4 -p 2 "apt update"

# Custom SSH key and port
pexec -H web1 -i ~/.ssh/mykey --port 2222 "whoami"

Options

Flag Description
--config YAML config file (default: ~/.pexec.yaml)
-c, --cmd Command to run (repeatable; all run in one session)
-s, --script Local script file to execute on remote hosts
--login Use a login shell (sources ~/.profile, ~/.bashrc)
--shell Custom shell for sessions (default: bash -s)
-H, --hosts Comma-separated hosts (repeatable)
-f, --hosts-file File with hosts, one per line
-u, --user SSH user for all hosts
-p, --parallel Max parallel connections (0=unlimited)
-t, --timeout SSH connect timeout in seconds (default: 30)
--stream Stream output in real-time
--json Output as JSON
--no-strict Disable strict host key checking
-i, --identity SSH private key path
--port SSH port

How session mode works

When you use -c multiple times, pexec joins all commands with newlines and pipes them into bash -s (or bash -ls with --login) over a single SSH connection. This means:

  • Environment variables set or sourced in earlier -c commands are available in later ones
  • cd in one command affects subsequent commands
  • It behaves like typing commands into an interactive shell

Default Hosts File

If no hosts are specified, pexec looks for ~/.pexec_hosts.

Contributors

zyongye

Issues