How to Execute Parallel SSH Commands on Multiple Servers from macOS


2 views

As a sysadmin or DevOps engineer working on macOS, you'll frequently need to execute identical commands across multiple servers. While you could manually SSH into each machine, this approach becomes impractical when managing dozens or hundreds of servers.

macOS offers several powerful tools for parallel SSH execution:

# Install pssh via Homebrew
brew install pssh

# Basic parallel SSH command
parallel-ssh -i -H "server1.example.com server2.example.com" -l username "uptime"

For interactive multi-server management:

brew install clusterssh
cssh server1 server2 server3

For more complex operations, consider Ansible:

# Install Ansible
brew install ansible

# Create inventory file
echo "[webservers]
server1.example.com
server2.example.com" > inventory.ini

# Run command on all servers
ansible webservers -i inventory.ini -a "df -h"

First, configure your SSH config file (~/.ssh/config):

Host *.example.com
  User adminuser
  IdentityFile ~/.ssh/id_rsa
  StrictHostKeyChecking no

For simple cases, a bash script works well:

#!/bin/bash
servers=("server1" "server2" "server3")
command="sudo apt update && sudo apt upgrade -y"

for server in "${servers[@]}"
do
  ssh "$server" "$command" &
done
wait

When executing parallel SSH commands:

  • Use SSH keys instead of passwords
  • Limit sudo privileges
  • Consider using a jump host for sensitive environments

Managing multiple Linux servers simultaneously is a common requirement for DevOps engineers and system administrators. When you need to deploy configuration changes, run maintenance scripts, or gather system information across your server fleet, executing commands manually on each machine becomes impractical.

While macOS includes the built-in ssh command, executing the same command across multiple servers requires either:

  • Manual connection to each server
  • Writing complex shell scripts with loops
  • Maintaining server lists in separate files

1. pssh (Parallel SSH)

The most robust solution is to install pssh (Parallel SSH) via Homebrew:

brew install pssh

Basic usage example:

pssh -h servers.txt -l username -A -i "uptime"

2. ClusterSSH

For interactive parallel sessions:

brew install clusterssh
cssh server1 server2 server3

3. Ansible Ad-Hoc Commands

For more advanced orchestration:

ansible all -i inventory.ini -m shell -a "df -h"

Example 1: Batch Updates

pssh -h production_servers.list -l deploy -i "sudo apt update && sudo apt upgrade -y"

Example 2: Status Checking

pssh -h webservers.txt -l admin -P "systemctl status nginx"

Example 3: File Distribution

pscp -h servers.txt -l user config.json /etc/app/config.json

For regular maintenance tasks, consider creating a shell script:

#!/bin/bash
SERVERS=("web1.example.com" "web2.example.com" "db1.example.com")

for server in "${SERVERS[@]}"; do
    ssh admin@$server "$1"
done

Always use SSH keys instead of passwords. Generate keys with:

ssh-keygen -t ed25519
ssh-copy-id user@server

For sensitive operations, implement proper sudo configurations and consider using SSH certificates instead of raw keys.