1

Title states the question. I have to run terminal command(s) on multiple systems at the same time. For instance, I have to run sudo apt install -y firefox on every computer on the same network. Say, I have the list of IP address of all computers with me and the username and password of every computer is identical. All systems run either Ubuntu 20.04 LTS or 16.04 LTS. The purpose of this, is to save time running the command(s) on 100+ computers manually.

In short, A computer acts as Admin, and runs commands on other computers.

La Corazón
  • 763
  • 3
  • 9
  • 22

3 Answers3

2

Note: The question originally asked about running commands simultaneously on several machines - hence my first solution was using Tmux. This is probably not suited for 100s of machines at once.

Use Tmux (fully or partially manual) or write a script (fully automatic).

It is advised to get familiar with the Tmux commands and shortcuts - preferably by making your own config. But here's how to do it (manually) with default config.

Start new session:

tmux new -s mysession

Split the window into X panes:

  • Ctrl + b, then % (split horizontal)
  • Ctrl + b, then " (split vertical)

Navigate around the panes with Ctrl + b, then Arrow keys

On each pane, SSH into a different machine:

ssh user@host

Enter command mode:

  • Ctrl + b, then :. Then type: setw synchronize-panes (now every command is sent to all panes)

Enter the command you wish to run:

sudo apt install -y firefox

This will now run via SSH on every machine.

You can also write a script that uses Tmux to connect to your list of IP's. And then you can run the commands manually in sync mode, or by the script also.

I'd say if you have 10s of machines, I would use Tmux. If you have 100s of machines, consider making this fully automated by a script.

Reference: Tmux Cheat Sheet.

Artur Meinild
  • 31,035
0

Here is one possible solution, within the references at the end of the answer are provided topics with more details. Here is how the script described below works.

enter image description here

1. Create executable script file, named populate-ssh-cmd. Place it into your user's ~/bin (or /usr/local/bin) directory to be accessible as shell command.

cat ~/bin/populate-ssh-cmd
#!/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 'Host\s\Klan-.*' "$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 logs

while IFS= read -r host do echo -e '\n\033[1;33m'"HOST: ${host}"'\033[0m' ssh -n "$host" "$CMD_EXEC 2>&1" | tee -a "/tmp/$(basename "${0}").${host}.log" done <<< "$HOSTS"

chmod +x ~/bin/populate-ssh-cmd

Note:

  • 2>&1 will redirect the remote STDERR to STDOUT, that is piped to the tee command, which will display it and also will write it to a separate log file for each remote host. To list the log files type ls -la /tmp/populate-ssh-cmd.sh.lan-*.

  • The script will ask for the remote admin's sudo passwords only once so the admins for all remote instances must have the same password.

2. Add entries for the LAN hosts in your ~/.ssh/config file and prefix their names by lan-. So the ~/.ssh/config file should look like as the follow.

Host lan-1-some-additional-info
    HostName 192.168.1.101
    IdentityFile ~/.ssh/lan-hosts/id_rsa
    User remoteUser

Host lan-2-some-additional-info HostName 192.168.1.102 IdentityFile ~/.ssh/lan-hosts/id_rsa User remoteUser

Host lan-3-some-additional-info HostName 192.168.1.103 IdentityFile ~/.ssh/lan-hosts/id_rsa User remoteUser

3. Use the populate-ssh-cmd script in a way as this.

populate-ssh-cmd sudo apt install -y firefox

The above script uses SSH key based authentication which is easier for such implementation and much secure than using password. If you want to use password based authentication you can implement sshpass -p 'footbar' as it is described within these references:

pa4080
  • 30,621
0

I do something similar that is quite easy after setup. I create aliases in the master PC for each computer so I can just type 3 letters for each of 10 computers to ssh into each and do a tab for each. Also aliases for update and upgrade and I can do all 10 in a few minutes. For example one tab su1, next one su2 etc and then in each tab type ud for apt-get update -y, then when done in each tab type dug for and apt-get dist-upgrade -y. So I can do 10 almost as fast as one by quickly switching to each terminal tab. I also do a few other commands this way.