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.

  • 4
    you can write a script to ssh into each of the ips using the username and password and run the command – Esther Apr 11 '22 at 18:21
  • 3
    That is what "puppet master" does. 1 system is the master, the others are puppets and can get instructions from the master (like upgrading or installing) – Rinzwind Apr 11 '22 at 18:40
  • @Esther I want to run a command on multiple systems at the same time on the same network. Writing a script to ssh into all of the systems and then run the command, seems to work. I'll check and get back. Thanks. – La Corazón Apr 11 '22 at 18:40
  • 1
    fyi this is an example of doing an update+upgrade: ssh root@{host} sh -c "apt update && apt -y upgrade" – Rinzwind Apr 11 '22 at 18:42
  • @Rinzwind And how am I supposed to do that? Is there any other option than the SSH method Esther just told ? – La Corazón Apr 11 '22 at 18:42
  • @Rinzwind {host} is to be replaced by the IP of the system where the command is to be executed? – La Corazón Apr 11 '22 at 18:44
  • 1
    yes and you probably want a password too Do investigate puppet master. It is an elaborate tool that can do this (one time setup) parallel-ssh is a cool tool too for this – Rinzwind Apr 11 '22 at 20:01
  • And what if there's a Firefox SNAP version installed? Or a previous Firefox APT version? – heynnema Apr 11 '22 at 21:37
  • Depending on the exact nature of the task(s) you want to execute in parallel, or how involved it is, you may want to look into task runners like rake or Grunt (to name just two arbitrarily chosen), or even go to a full-blown orchestration solution like Ansible. – Henning Kockerbeck Apr 12 '22 at 10:50

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
  • 26,018
  • 1
    It sounds like the goal is not that they be installed simultaneously, but rather not having to do any particular step for each machine. – Esther Apr 11 '22 at 18:30
  • 1
    I agree. For the particular scenario, a script is possibly the best solution. But judging from the title, I believe using Tmux could also be helpful in some situations where it's not batch installation of 100s of machines. – Artur Meinild Apr 11 '22 at 18:32
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
  • 29,831
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.