SSH::Batch - Simple remote shell commands

Perl | DevOps | SSH | - September 15, 2014 // Barry

SSH::Batch is a simple command line tool, written in Perl, that allows you to run shell commands over SSH across multiple servers. These days it seems most people turn to Puppet / Chef / Ansible for that type of thing, but sometimes your needs aren't that complicated. For that, SSH::Batch fills the gap nicely and it's really simple to get started.

I was caught off-guard last week when I made a quick tweet about a simple but handy Perl tool called SSH::Batch and it generated more interest than generally anything else that I've posted on Twitter. Taking a hint, I figured it was worth assembling a quick instructional on the tool for people who want to get their feet wet.

Why Perl?

Well, Perl has been around forever. It's natively included on every Unix/Linux based system and has been for a very long time. From a Sysadmin standpoint, Perl is a language that you can always count on having available and because of that there are a lot of excellent command line tools built with Perl (that are really fast too). 

As is the case with just about every piece of programming technology out there, most things you see have been around long before you heard about them - just in different languages. Even CFEngine predates Puppet, Chef, Ansible, etc by a long time and has a much lower RAM commitment by comparison too.

But let's face it. Perl is not new, trendy, or particularly legible to somebody who doesn't natively speak Regex. If you were concerned about having to use Perl to use SSH::Batch, set your mind at ease because you won't be using anything but shell scripts.


Let's get setup. First off, if you've never used Perl before you should know that you'll be installing via CPAN, which is basically a package manager for Perl libraries that predates most others you've ever heard of. If you'll pull up a *nix terminal (Cygwin should work if you're on a Windows machine) just type 

sudo cpan -i SSH::Batch

And press enter to get started. On most systems, the cpan command will need to be run as root. It can be run as the user, but it's more complicated and sometimes prone to issues including failing tests on module installations.

Now, to demonstrate this I'm creating three "droplets" on Digital Ocean but you may feel free to use any virtual machines where you have SSH access. 

To start our demonstrations, open your terminal and create a file called ~/.fornodesrc with the following contents:

[email protected] [email protected] [email protected]

Replace those ip addresses with the ips or DNS addresses of your servers. We're starting simple here. I've just created these servers so by default it will expect me to login to them as root. If you don't specify a username, just as with the SSH command it will assume your current username. You can also add a specific SSH port with a :<PORT> on the end as well.

Because I'm using Digital Ocean, my virtual servers have been created with my SSH key already installed. That means that I will not have to enter a password whenever I ssh to these machines, which is fairly critical for distributing scripting. You can either read this great guide on how to generate and copy over your SSH keys or you can use SSH::Batch to copy them for you like so...

$ key2nodes '{droplets}'

You will prompted for a password that will be used to log you into those machines and copy up your public key. Whichever method you choose to get your keys pushed up, let's run some commands.

$ atnodes 'hostname' '{droplets}'
===================== [email protected] =====================
===================== [email protected] =====================
===================== [email protected] =====================

The syntax you see above is "atnodes 'command' 'servers'" followed by the result of that command on each machine. The quoted command can be anything you'd type at a command prompt. The servers argument is evaluated by the fornodes command which can do a lot of manipulation of sets by combining, removing, allowing shorthand for ranges and sets, etc.

There's a simple example of taking our set of three and removing one from the actionable set. You can use the fornodes command to easily test the validity of your server combinations. Refer to the SSH::Batch documentation for more examples.

You can also transfer files. To demonstrate I'm going to upload a copy of Clemson's Tiger Paw logo that I happen to have on my machine using the `tonodes` command.

$ tonodes paw.png '{droplets}:.'
===================== [email protected] =====================
===================== [email protected] =====================
===================== [email protected] =====================

And that will transfer that file up to all of those machines. Whatever comes after the : in the server is the path to upload to. Upload's happen over SCP by default but you can also specify rsync.

Now let's verify that the file got there with a quick command...

$ atnodes 'ls -la | grep paw' '{droplets}'
===================== [email protected] =====================
-rw-r--r--  1 root root 349693 Sep 16 00:56 paw.png
===================== [email protected] =====================
-rw-r--r--  1 root root 349693 Sep 16 00:56 paw.png
===================== [email protected] =====================
-rw-r--r--  1 root root 349693 Sep 16 00:56 paw.png

And there we have it. Enjoy your SSH::Batch'n!