How to use parallel ssh (PSSH) for executing commands in parallel on a number of Linux/Unix/BSD servers

Recently I come across a nice little nifty tool called parallel ssh (PSSH) to run a single command on multiple Linux / UNIX / BSD servers. You can easily increase your productive with this SSH IT automation tool.

ADVERTISEMENTS

More about pssh

pssh is a command line tool for executing ssh in parallel on some hosts. It specialties includes:

  1. Sending input to all of the processes
  2. Inputting a password to ssh
  3. Saving output to files
  4. IT/sysadmin task automation such as patching servers or looking for error logs
  5. Timing out and more

Let us see how to install and use pssh on Linux and Unix-like system.

parallel ssh (PSSH)

parallel ssh (PSSH) installation

You can install pssh as per your Linux and Unix variant. Once package installed, you can get parallel versions of the openssh tools. Included in the installation:

  1. pssh command – Parallel ssh
  2. pscp command – Parallel scp
  3. prsync command – Parallel rsync
  4. pnuke command – Parallel nuke
  5. pslurp command – Parallel slurp

Install pssh on Debian/Ubuntu Linux

Type the following apt-get command/apt command to install pssh:
$ sudo apt install pssh
OR
$ sudo apt-get install pssh
Sample outputs:

Fig.01: Installing pssh on Debian/Ubuntu Linux

Fig.01: Installing pssh on Debian/Ubuntu Linux

Install pssh on Apple MacOS X

Type the following brew command:
$ brew install pssh
Sample outputs:

Install pssh to execute commands on multiple remote Linux and Unix servers

Fig.02: Installing pssh on MacOS Unix

Install pssh on FreeBSD unix

Type any one of the command:
# cd /usr/ports/security/pssh/ && make install clean
OR
# pkg install pssh
Sample outputs:

Fig.03: Installing pssh on FreeBSD

Fig.03: Installing pssh on FreeBSD

Install pssh on RHEL/CentOS/Fedora Linux

First turn on EPEL repo and type the following command yum command:
$ sudo yum install pssh
Sample outputs:

Fig.04: Installing pssh on RHEL/CentOS/Red Hat Enterprise Linux

Fig.04: Installing pssh on RHEL/CentOS/Red Hat Enterprise Linux

Install pssh on Fedora Linux

Type the following dnf command:
$ sudo dnf install pssh
Sample outputs:

Fig.05: Installing pssh on Fedora

Fig.05: Installing pssh on Fedora

Install pssh on Arch Linux

Type the following command:
$ sudo pacman -S python-pip
$ pip install pssh

Set passwordless SSH using public-private key pairs

It is recommend that you set up ssh keys for automation. To generate a key pair run the ssh-keygen command:
ssh-keygen
Next transfer the public key to the remote host using the ssh-copy-id command:
ssh-copy-id user@server-ip
ssh-copy-id vivek@dellm6700
ssh-copy-id root@192.168.2.30
ssh-copy-id root@192.168.2.45
ssh-copy-id root@192.168.2.46

Test it using the ssh command:
ssh vivek@dellm6700
ssh root@192.168.2.30

See my previous tutorials SSH Public Key Based Authentication on a Linux/Unix server and set up SSH Keys on a Linux / Unix System for more information on passwordless SSH topics.

How to use pssh command

First you need to create a text file called hosts file from which pssh read hosts names. The syntax is pretty simple. Each line in the host file are of the form [user@]host[:port] and can include blank lines and comments lines beginning with “#”. Here is my sample file named ~/.pssh_hosts_files:
$ cat ~/.pssh_hosts_files
vivek@dellm6700
root@192.168.2.30
root@192.168.2.45
root@192.168.2.46

Run the date command all hosts:
$ pssh -i -h ~/.pssh_hosts_files date
Sample outputs:

[1] 18:10:10 [SUCCESS] root@192.168.2.46
Sun Feb 26 18:10:10 IST 2017
[2] 18:10:10 [SUCCESS] vivek@dellm6700
Sun Feb 26 18:10:10 IST 2017
[3] 18:10:10 [SUCCESS] root@192.168.2.45
Sun Feb 26 18:10:10 IST 2017
[4] 18:10:10 [SUCCESS] root@192.168.2.30
Sun Feb 26 18:10:10 IST 2017

Run the uptime command on each host:
$ pssh -i -h ~/.pssh_hosts_files uptime
Sample outputs:

[1] 18:11:15 [SUCCESS] root@192.168.2.45
 18:11:15 up  2:29,  0 users,  load average: 0.00, 0.00, 0.00
[2] 18:11:15 [SUCCESS] vivek@dellm6700
 18:11:15 up 19:06,  0 users,  load average: 0.13, 0.25, 0.27
[3] 18:11:15 [SUCCESS] root@192.168.2.46
 18:11:15 up  1:55,  0 users,  load average: 0.00, 0.00, 0.00
[4] 18:11:15 [SUCCESS] root@192.168.2.30
 6:11PM  up 1 day, 21:38, 0 users, load averages: 0.12, 0.14, 0.09

You can now automate common sysadmin tasks such as patching all servers:
$ pssh -h ~/.pssh_hosts_files -- sudo yum -y update
OR
$ pssh -h ~/.pssh_hosts_files -- sudo apt-get -y update
$ pssh -h ~/.pssh_hosts_files -- sudo apt-get -y upgrade

How do I use pssh to copy file to all servers?

The syntax is:
pscp -h ~/.pssh_hosts_files src dest
To copy $HOME/demo.txt to /tmp/ on all servers, enter:
$ pscp -h ~/.pssh_hosts_files $HOME/demo.txt /tmp/
Sample outputs:

[1] 18:17:35 [SUCCESS] vivek@dellm6700
[2] 18:17:35 [SUCCESS] root@192.168.2.45
[3] 18:17:35 [SUCCESS] root@192.168.2.46
[4] 18:17:35 [SUCCESS] root@192.168.2.30

Or use the prsync command for efficient copying of files:
$ prsync -h ~/.pssh_hosts_files /etc/passwd /tmp/
$ prsync -h ~/.pssh_hosts_files *.html /var/www/html/

How do I kill processes in parallel on a number of hosts?

Use the pnuke command for killing processes in parallel on a number of hosts. The syntax is:
$ pnuke -h .pssh_hosts_files process_name
kill nginx and firefox on hosts:
$ pnuke -h ~/.pssh_hosts_files firefox
$ pnuke -h ~/.pssh_hosts_files nginx

See the pssh/pscp command man pages for more information.

Conclusion

pssh is a pretty good tool for parallel SSH command execution on many servers. It quite is useful if you have 5 or 7 servers or VMs. Nevertheless, if you need to do something complicated you should look into Ansible and co. See the official site here for more info.

🐧 Get the latest tutorials on SysAdmin, Linux/Unix, Open Source & DevOps topics via:
CategoryList of Unix and Linux commands
File Managementcat
FirewallCentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network Utilitiesdig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNCentOS 8 Debian 10 Firewall Ubuntu 20.04

ADVERTISEMENTS
5 comments… add one
  • Nobody Feb 26, 2017 @ 20:04

    I rather use Ansible – the simplest way to automate apps and IT infrastructure :)

    • Davama Feb 27, 2017 @ 23:05

      @nobody
      Was actually going to mention ansible too

  • Seshadri Kothandaraman Feb 27, 2017 @ 3:22

    Neat utility ! I have used a similar utility in the past, called pdsh.
    Not sure about other flavours, but apt installs the parallel-ssh binary and not pssh – one can always create a link, though
    Thanks !

  • William Peckham Feb 27, 2017 @ 15:43

    Pssh is ok, but I prefer mpssh. I can define groups of hosts and call by name.

  • cc Mar 13, 2017 @ 1:04
    from "violent python"
    
    #!./env/bin/python
    
    """ SSH Botnet
    
        This script logs into several different machines with ssh and sends
        commands to each of them in tandem
    
        Don't be a moron, please don't use this for something illegal.
    
        Usage:
            ssh_botnet.py
            ssh_botnet.py (-h | --help)
            ssh_botnet.py (-v | --version)
    
        Options:
            -h --help       Show this screen.
            --version       Show version
    """
    
    import pxssh
    from docopt import docopt
    from colorama import Fore, init
    
    
    class Client:
        def __init__(self, host, user, password):
            self.host = host
            self.user = user
            self.password = password
            self.session = self.connect()
    
        def connect(self):
            try:
                ssh = pxssh.pxssh()
                ssh.login(self.host, self.user, self.password)
    
                return ssh
            except Exception, e:
                print Fore.RED + '[-] Error Connecting' + Fore.RESET
                print e
    
        def send_command(self, cmd):
            self.session.sendline(cmd)
            self.session.prompt()
    
            return self.session.before
    
    
    def botnet_command(command, botnet):
        for client in botnet:
            output = client.send_command(command)
            print Fore.GREEN + '[*] Output from ' + client.host + Fore.RESET
            print '[+] ' + output + '\n'
    
    
    def add_client(host, user, password, botnet):
        client = Client(host, user, password)
        botnet.append(client)
    
    
    def main():
        botnet = []
    
        add_client('10.10.10.110', 'root', 'toor', botnet)
        add_client('10.10.10.120', 'root', 'toor', botnet)
        add_client('10.10.10.130', 'root', 'toor', botnet)
        botnet_command('uname -v', botnet)
    
    
    if __name__ == '__main__':
        init()
        docopt(__doc__, version=0.1)
        main()
    

Leave a Reply

Your email address will not be published. Required fields are marked *

Use HTML <pre>...</pre>, <code>...</code> and <kbd>...</kbd> for code samples.