Since you're using key-based authentication with SSH, it is easy to automate running a command on many machines. You can write a simple script to do this, but you don't really need to. You can do it with a single command, something like:
xargs -a IP_list.txt -d'\n' -I{} ssh {} 'printf "\n%s:\n" {}; lsb_release -a' | tee -a LSB_Release_Info.txt
This runs one ssh
command for each line of IP_list.txt
, plugging the line in for {}
. For this to work, each line should be an IP address or hostname of a server you want to SSH to. Suppose, for example, that IP_list.txt
contains the line 192.168.10.2
. Then the SSH command that xargs
runs for that line is:
ssh 192.168.10.2 'printf "\n%s:\n" 192.168.10.2; lsb_release -a'
What ssh
does with that command is to attempt to connect to 192.168.10.2 and to execute this code in a non-interactive shell:
printf "\n%s:\n" 192.168.10.2; lsb_release -a
That consists of two commands. The first prints a blank line followed by the line 192.168.10.2:
. The second is lsb_release -a
.
The ssh
command can only succeed if you are logging in with the correct credentials:
- As I've written it, your local username will be used. If that's not correct, you'll have to modify the command accordingly. For example, if all the machines have the same username as one another--e.g.,
foo
--then you'd write ssh foo@{}
in place of ssh {}
.
- As you probably know, you'll need to cache your decrypted private key with an authentication agent, to avoid needing to type your local SSH key passphrase in for each
ssh
command. My guess is that you have this set up already; if not, see man ssh-agent
. (Likely it is sufficient to run eval "$(ssh-agent)"
followed by ssh-add
, and enter your passphrase.)
Piping the output of that xargs
command with the |
operator to tee -a LSB_Release_Info.txt
shows you the output while also appending it to the (local) file LSB_Release_Info.txt
. Error messages are not included in the file; those will only be shown to you. If you wanted to include them in the output file, you could use |&
instead of |
, but you're very unlikely to want them. More likely, you might only want to see error messages, in which case you can use >>LSB_Release_Info.txt
instead of | tee -a LSB_Release_Info.txt
--that is, just redirect to the file instead of piping to tee
. Note that if you run tee
without -a
, or if you use >
instead of >>
, then you are overwriting LSB_Release_info.txt
instead of appending to it.
I suggest testing this out first with an input file consisting of just a few IP addresses. Pressing Ctrl+C usually succeeds at stopping a long-running command, but I still suggest doing a bit of testing to get it right before running it for all your servers. For example, to write this answer I tested this on my local network with four IP addresses, and got output to my terminal (and in LSB_Release_Info.txt
) like this:
192.168.10.2:
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionic
192.168.10.4:
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.6 LTS
Release: 16.04
Codename: xenial
192.168.203.128:
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu Eoan Ermine (development branch)
Release: 19.10
Codename: eoan
192.168.31.130:
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionic
That's what the output should look like with the command given above. You can adjust the command accordingly, then run it on all two hundred servers once it produces the output format you want.
pssh
and then runningparallel-ssh -h IP_list.txt -P lsb_release -r > LSB_Release_Info.txt