Just thought I'll share small script I made to run same commands on multiple Linux servers quickly. I expanded my original script little bit, so it works also with password authentication and not just with ssh keypair.
To make it work it needs to have hosts.txt file in same folder which has following form per line:
[server];[user];[password]
If ssh keys are used to authenticate, then "pk" string is put as [password](without "") and for different port then just using [server:port] works. Not really fond of the idea of storing passwords in file, but with use of gpg or something file can ofc. be encrypted/decrypted when needed. I would have most likely tried to implement encryption/decryption to script if I wouldn't use keypairs. The script uses
fabric for handeling ssh connections and it can be installed with pip.
But usage goes like this:
$ rexecute.py [command to run]
Here's the code, pretty simple and nothing new, but just my quick implementation of such task.
from fabric.api import *
from fabric.tasks import execute
import sys
"""
rexecute.py
author: gray-fox
"""
class remote(object):
def read_targets(self):
"""
hosts.txt line pattern.
One host per line:
[host];[user];[password]
Run on specific port:
[host:<port>]
If authentication is made with ssh keys use "pk" as
[password]
"""
self.hosts = []
self.users = []
self.passwords = []
with open('hosts.txt','r') as h:
for self.l in h:
self.params = self.l.split(';', 2)
self.hosts.append(self.params[0])
self.users.append(self.params[1])
self.passwords.append(self.params[2])
return (self.hosts, self.users, self.passwords)
def execute(self, cmd_raw):
self.failed = []
self.cmd = cmd_raw.split()
self.servers,self.users,self.passwords = self.read_targets()
for self.s, self.u, self.p in zip(self.servers, self.users, self.passwords):
if self.p != "pk":
with settings(host_string=self.s, user=self.u, password=self.p):
try:
if "sudo" in self.cmd:
self.cmd.remove('sudo')
sudo(' '.join(self.cmd))
else:
run(' '.join(self.cmd))
except Exception as e:
self.failed.append(self.t)
print "Execution failed on: "+self.t
print "Error:"+str(e)
else:
#Change path to match your private key
with settings(host_string=self.s, user=self.u, key_filename="~/.ssh/id_rsa"):
try:
if "sudo" in self.cmd:
self.cmd.remove('sudo')
sudo(' '.join(self.cmd))
else:
run(' '.join(self.cmd))
except Exception as e:
self.failed.append(self.t)
print "Execution failed on: "+self.t
print "Error:"+str(e)
if len(self.failed) == 0:
print "Command executed on all servers"
else:
print "[!] Execution failed on:"
for f in self.failed:
print f
if __name__=='__main__':
if len(sys.argv) >= 2:
remote().execute(' '.join(sys.argv[1:]))
elif len(sys.argv) < 2:
sys.exit("[!] No command specified")