TechnoBleed - Cyber Securiy and Technology Blog

How to run a single command on multiple Linux machines at once

Linux logo
Image: Shutterstock

I’m always looking for ways to make my work more efficient, so the last thing I want to have to do is log into multiple Linux machines and run a single command on each. I’d much rather have the ability to run that command on multiple machines at once.

SEE: 40+ open source and Linux terms you need to know (TechRepublic Premium)

Of course, there are apps for that. But since this is Linux, wouldn’t it make more sense to piece together your own solution? Of course, it would. After all, Linux is about choice, power and flexibility.

Say, for example, you had several Ubuntu Servers and you wanted to run sudo apt-get update and sudo apt-get upgrade on them all at once. You don’t have to log in to each of those machines to run those commands, not when there are scripts to handle that task for you.

I’ve found such a script and have modified it in a way that you can use it to create multiple scripts for specific hosts (such as Ubuntu- or RHEL-based servers). Let’s take a look at this script and see how to make it work.

What you’ll need

To use this script you’ll need a Linux machine to run the command and Linux servers to send commands to. Depending on the command you want to run on the remote servers, you’ll need a user with sudo privileges.

That’s it. Let’s make some magic.

How to configure SSH

The first thing we must do is create an SSH config file that will define our remote hosts. But there’s a trick to this particular setup. We’re going to define hostnames that begin with either ubuntu- or rhel-, depending on the operating system for each.

On the system you’ll be running the script, create the SSH config file with the command:

nano ~/.ssh/config

Let’s say we have the following:

Ubuntu-based systems on IP addresses 192.168.1.11 and 192.168.1.13 and an RHEL-based machine on IP address 192.168.1.14. Our config file might look like this:

Host rhel-db1

   Hostname 192.168.1.14

Host ubuntu-invoice
   Hostname 192.168.1.11

Host ubuntu-portainer
   Hostname 192.168.1.13

Save and close the file.

How to create the script

Now, we’ll create two scripts, one for Ubuntu servers and one for RHEL servers. Create the Ubuntu server script with the command:

nano ~/ubuntu-cmd

In that file, paste the following:

!/bin/bash

# Get the user's input as command
[[ -z ${@} ]] && exit || CMD_EXEC="${@}"

# Get the hosts from ~/.ssh/config whose names are prefixed by `lan-`
HOSTS=$(grep -Po ‘HostsKubuntu-.*’ “$HOME/.ssh/config”)

# Test weather the input command uses sudo
if [[ $CMD_EXEC =~ ^sudo ]]
then
    # Ask for password
    read -sp '[sudo] password for remote_admin: ' password; echo

    # Rewrite the command
    CMD_EXEC=$(sed "s/^sudo/echo '$password' | sudo -S/"     "$CMD_EXEC")
fi

# loop over the hosts and execute the SSH command, remove `-a` to override the>
while IFS= read -r host
do
   echo -e 'n33[1;33m'"HOST: ${host}"'33[0m'
   ssh -n "$host" "$CMD_EXEC 2>&1" | tee -a "/tmp/$(basename "${0}").${host}.>
done <<< "$HOSTS"

Save and close the file. Next, create the RHEL script with the command:

nano ~/rhel-cmd

In that file, paste the following:

#!/bin/bash

# Get the user's input as command
[[ -z ${@} ]] && exit || CMD_EXEC="${@}"

# Get the hosts from ~/.ssh/config whose names are prefixed by `lan-`
HOSTS=$(grep -Po 'HostsKrhel-.*' "$HOME/.ssh/config")

# Test weather the input command uses sudo
if [[ $CMD_EXEC =~ ^sudo ]]
then
   # Ask for password
   read -sp '[sudo] password for remote_admin: ' password; echo

   # Rewrite the command
   CMD_EXEC=$(sed "s/^sudo/echo '$password' | sudo -S/" <<< "$CMD_EXEC")
fi

# loop over the hosts and execute the SSH command, remove `-a` to override the>
while IFS= read -r host
do
   echo -e 'n33[1;33m'"HOST: ${host}"'33[0m'
   ssh -n "$host" "$CMD_EXEC 2>&1" | tee -a "/tmp/$(basename "${0}").${host}.>
done <<< "$HOSTS"

Save and close the file. Move those files to a directory in your path, such as with the command:

sudo cp ubuntu-cmd rhel-cmd /usr/local/bin

Change the ownership of those scripts with:

sudo chown $USER /usr/local/bin/ubuntu-cmd
sudo chown $USER /usr/local/bin/rhel-cmd

We now have our Ubuntu and RHEL hosts defined in our SSH config file and our scripts that are globally executable. Let’s first run the Ubuntu script and send the sudo apt-get update command to our Ubuntu servers. For that, the command would be:

ubuntu-cmd sudo apt-get update

The script will check the SSH config file for any host that starts with ubuntu and then prompt you for both your sudo password and your remote user password for each host. It should successfully run the apt-get update command on any Ubuntu server found in the SSH config file.

Next, we’ll run sudo dnf update on our RHEL hosts with the command:

rhel-cmd sudo dnf update

The same thing will happen, only the dnf update command will run on our RHEL-based hosts defined in the SSH config file.

And that’s all there is to creating a script to run a command on multiple hosts defined in your SSH config file. Use this setup to see what other clever things you can do because that’s part of the power of Linux.

Subscribe to TechRepublic’s How To Make Tech Work on YouTube for all the latest tech advice for business pros from Jack Wallen.

Bagikan

Leave a Comment