At the company I work at, we have no real way to quickly execute shell commands on all of our customers systems, which often results in what we call Tiny Tim
tasks, where the list of all of our systems is split between the 5 devs we have, and we simply go through one-by-one, SSHing into each one and executing the necessary commands.
To streamline this process, I created a script in Python3 using Paramiko for SSH.
The script takes the path to a private OpenSSH key from command-line args, reads a list of hosts from a file called hosts.txt
(lines in this file can be commented by prepending them with --
), and a list of shell commands from a file called cmds.txt
. Due to the way we set up our customers' systems, each domain has 2 servers, so the script loops over each host in the list twice, prepending disc1.
and disc2.
respectively to send the commands to both servers.
from paramiko.client import AutoAddPolicy
from paramiko.client import SSHClient
import sys
from sys import argv
if len(argv) < 2:
print("Invalid args!")
print("Usage: python3 run.py <private ssh key filepath>")
exit()
with open('cmds.txt') as c:
cmds = c.readlines()
with open('hosts.txt') as f:
lines = f.readlines()
for line in lines:
for i in range(1, 3):
line = line.strip()
host = "disc%s.%s" % (i, line)
if line.startswith('--'):
print("Host %s began with --, skipping" % line)
continue
client = SSHClient()
client.set_missing_host_key_policy(AutoAddPolicy)
client.load_system_host_keys()
try:
print("[%s]> Connecting as root on port 22..." % host)
client.connect(host, 22, 'root', None, None, argv[1])
except KeyboardInterrupt:
break
except Exception as err:
print("[%s]> Connection failed: %s" % (host, err))
continue
for c in cmds:
print("[%s]> Executing %s..." % (host, c.strip()))
stdin, stdout, stderr = client.exec_command(c)
print(stdout.read().decode('utf-8'))
print(stderr.read().decode('utf-8'))
client.close()
print("[%s]> Done" % host)
I ran it through PEP8 and surprisingly didn't get any errors or warnings, but it's still quite messy and I'd appreciate feedback.
pxssh
frompexpect
. It makes such tasks much simpler. \$\endgroup\$