I am trying to automate these steps so that I don't need to do this on every machines manually. I need to install latest app server software (abc.tar.gz) on all the unix boxes.

I need to do this in around 12 machines - "machine1" ... "machine12". I have a master machine "machine0" which has abc.tar.gz file so I was thinking to run my script from this machine only and install abc.tar.gz software by following below steps in all those 12 machines one by one. My unix account id is david and my process runs as golden user.

This is the steps I follow if I am installing abc.tar.gz in "machine1":

david@machine1:~$ sudo scp david@machine0:/home/david/abc.tar.gz .
david@machine1:~$ sudo stop test_server
david@machine1:~$ sudo su - golden
golden@machine1:~$ cd /opt/process
golden@machine1:/opt/process$ rm -rf *
golden@machine1:/opt/process$ exit
david@machine1:~$ sudo cp abc.tar.gz /opt/process
david@machine1:~$ sudo chown -R golden /opt/process
david@machine1:~$ sudo su - golden
golden@machine1:~$ cd /opt/process
golden@machine1:/opt/process$ tar -xvzf abc.tar.gz
golden@machine1:/opt/process$ exit
david@machine1:~$ sudo start test_server

How can I automate this so that it can do the same steps in all 12 machines one bye one? I mean install abc.tar.gz in machine1 first, then install on machine2 and go on.. I want to run this script from machine0 only.

Is there any way to automate this?


I would recommend a provisioning tool such as Fabric or Ansible for this. Both are fairly easy to set up, and will allow you to do more the just the command you need in this case, since you be able to build off you initial playbooks or fabfile depending on which tool you go with.

Docs for Fabric can be found here: http://docs.fabfile.org/en/1.10/ Docs for Ansible can be found here: http://docs.ansible.com/ansible/intro_getting_started.html

You'll need some comfort with SSH keys and SSH configurations for both tools, which you can find in the docs as well.

  • Ansible would be my tool of choice for a one-off action; I may look into Fabric. For long term stability as opposed to quick hacks, I prefer CFEngine for its declarative language based on a clear understanding of the relativity of knowledge and its use of promise theory. – Wildcard Mar 30 '16 at 1:06
  • Completely agree, while I don't dislike Fabric I enjoy the clean readability of Ansible more. – cgutshal Mar 30 '16 at 3:24
  • @cgutshal thanks for suggestion. I have not used either of these tools. If possible can you provide an example how can I use either of them? I need to set these up in my production environment so which one do you think is reliable and best? – user1950349 Mar 30 '16 at 19:05
  • @user1950349 You'll need to work through the docs for which ever tool you go with. Edited the main post with links for this. – cgutshal Mar 30 '16 at 22:47

pdsh can do what you want. By default, it will operate on several machines at once in parallel, but you can use the -f option to limit it to running on each machine one at a time if you want.


# copy abc.tar.gz to /home/david on machine1..machine12
pdcp -w machine[1-12] abc.tar.gz /home/david

# run a bunch of commands on machine1..machine12
# be careful of quoting
pdsh -w machine[1-12] 'sudo stop service ; do something ; do something else ;
                       sudo start service'

Alternatively, rather than put all the commands in single- or double-quotes on the pdsh command line, you can pdcp a shell script to the remote machines and run it with a single command.

pdcp -w machine[1-12] abc.tar.gz /home/david
pdcp -w machine[1-12] ./my-script.sh /tmp
pdsh -w machine[1-12] sh -c '/tmp/my-script.sh'

(use sh -c just in case /tmp is mounted noexec)

This is particularly useful if you want to avoid getting confused by having multiple levels of nested quotes (e.g. if you need to run some commands with sudo or su, or embed an awk or sed or whatever script). It's often a lot simpler to just write a normal shell (or awk or perl or whatever) script, copy it to where it's needed, and run it there.

pdsh also allows you to use a file called /etc/genders to define machines and what (arbitrary) attributes you assign to them. e.g.

machine0        master,all
machine[1-12]   machines,all
web[1-4]        webservers,all
db[1-2]         mysql,db,all

You can select the machines by attribute on the pdsh or pdcp command line with -g, e.g. pdcp -g machines abc.tar.gz /home/david or pdsh -g all uname -a or pdsh -g web,db,master uptime.

pdsh was written for use on HPC clusters, but i've found it to be equally useful for bulk-administering any group(s) of machines.

BTW, pdsh is a different kind of tool to puppet or ansible or cfengine etc - they're for installing and maintaining a consistent environment on a group of machines (such as a cluster or a VM farm etc). pdsh is more for running one-off commands and/or copies (to or from) on that same group of machines.

  • There's also a dshbak command which you can pipe pdsh output into which can do things like remove duplicate output. At least on centos 7.6 yum install pdsh also installs dshbak – lost Sep 12 '19 at 12:42
  • yep, i use dshbak frequently (esp. when the command i'm running with pdsh produces copious output). I think i've mentioned it a few times in other answers that refer to pdsh. – cas Sep 12 '19 at 12:47

In terms of a script, you might be looking at something like:

for machine in "${MACHINES[@]}"; do
  # insert sequence of setup steps here.

This is a quick and dirty way to have a deploy script across multiple machines. Of course, there are other more "professional" ways to do this task, but often this is sufficient and maintainable.


I prefer to use xargs for such tasks. As an example

cat serverlist.txt | xargs -I % sh -c 'ssh root@% 'date';'echo test''

And serverlist.txt contains IP/hostnames newline separated.

For a greater server park of cause it's better to use tools like ansible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.