How to connect to a server via ssh once and collect various commands into separate variables

greavette

New Member
Joined
Sep 12, 2019
Messages
4
Reaction score
0
Credits
0
Hello,

We use as bash script to connect to servers listed in an .csv file to issue commands against these servers and retrieve data to be saved in a .csv file. The data we want to collect is saved in variables. We issue an ssh command for each variable we want to capture. I'm thinking this is inefficient and slow and perhaps there is a better way to do this by connecting to the server through ssh once and issuing all the commands we need and still being able to save the commands in individual variables for our output file so I can decide in the output file to place the new commands we've captured as well as list some data from the input file into our final report.

Would someone be able to point me in the right direction on how I can connect once to a server via ssh, issue multiple commands to that server yet save the results from each command to their individual variable?

Here is what our script looks like:

Bash:
#!/bin/bash

SOURCE_FILE=/home/user/scripts/input.csv
if test -f "$SOURCE_FILE"; then
    echo "$SOURCE_FILE exists"
fi



REPORT_FILE="/home/user/scripts/Report_$(date +"%F_%T").csv"

echo $REPORT_FILE

UNREACHABLE="255"
INVALID_PASSWORD="5"
NO_HOME_DIRECTORY="2"
PASSWORD_EXPIRED="1"
FLAVOUR=""
HOSTNAME=""

touch $REPORT_FILE

       echo "Input Hostname,\
Input IP,\
SSH Access,\
Tag,\
OS Type,\
Hostname,\
IP Adress,\
Uptime,\
ACTIVE KERNEL,\
INACTIVE KERNELS"  >> $REPORT_FILE

exec < $SOURCE_FILE || exit 1
read header # read (and ignore) the first line
while IFS=, read -r InputHost\
InputIP\
Tag\
UserAgentTag\
ResourceProvisioner\
OSType\
OSVersion\
OSDetail\
Location\
PowerState\
; do
        sshpass -p '********' ssh -qno StrictHostKeyChecking=no -o ConnectTimeout=1 userlogin@$InputIP 'ls -l /home/userlogin >/dev/null 2>&1' > /dev/null 2>&1
       
        status="$(echo $?)"
       
        echo "processing $InputHost"
       
        FLAVOUR=$(sshpass -p '********' ssh -qno StrictHostKeyChecking=no -o ConnectTimeout=1 userlogin@$InputIP 'cat /etc/redhat-release 2>/dev/null || lsb_release -a 2>/dev/null | grep Description | cut -f2')
       
        HOSTNAME=$(sshpass -p '********' ssh -qno StrictHostKeyChecking=no -o ConnectTimeout=1 userlogin@$InputIP 'hostname')

        IPADDRESS=$(sshpass -p '********' ssh -qno StrictHostKeyChecking=no -o ConnectTimeout=1 userlogin@$InputIP 'hostname -I')
       
        ACTIVE_KERNEL=$(sshpass -p '********' ssh -qno StrictHostKeyChecking=no -o ConnectTimeout=1 userlogin@$InputIP 'uname -r')

        INACTIVE_KERNEL=$(sshpass -p '********' ssh -qno StrictHostKeyChecking=no -o ConnectTimeout=1 userlogin@$InputIP 'rpm -qa | grep '^kernel-[0-9]' |grep -vE `uname -r`')
       
        UPTIME=$(sshpass -p '********' ssh -qno StrictHostKeyChecking=no -o ConnectTimeout=1 userlogin@$InputIP 'uptime | cut -d "," -f 1')


        if [ "$status" == "$UNREACHABLE" ]
        then
                echo "$InputHost,\
                $InputIP,\
                cannot connect,\
                $Tag,\
                $FLAVOUR,\
                $HOSTNAME,\
                $IPADDRESS,\
                $UPTIME,\
                "$ACTIVE_KERNEL,\
                $INACTIVE_KERNEL >> $REPORT_FILE
        elif [ "$status" == "$INVALID_PASSWORD" ]
        then
                echo "$InputHost,\
                $InputIP,\
                invalid account access,\
                $Tag,\
                $FLAVOUR,\
                $HOSTNAME,\
                $IPADDRESS,\
                $UPTIME,\
                "$ACTIVE_KERNEL,\
                $INACTIVE_KERNEL >> $REPORT_FILE
        elif [ "$status" == "$NO_HOME_DIRECTORY" ]
        then
                echo "$InputHost,\
                $Tag,\
                $FLAVOUR,\
                $HOSTNAME,\
                $IPADDRESS,\
                $UPTIME,\
                "$ACTIVE_KERNEL,\
                $INACTIVE_KERNEL >> $REPORT_FILE

        elif [ "$status" == "$PASSWORD_EXPIRED" ]
        then
                echo "$InputHost,\
                $InputIP,\
                password expired,\
                $Tag,\
                $FLAVOUR,\
                $HOSTNAME,\
                $IPADDRESS,\
                $UPTIME,\
                "$ACTIVE_KERNEL,\
                $INACTIVE_KERNEL >> $REPORT_FILE
        else
             echo "$InputHost,\
                $InputIP,\
                successful ssh access,\
                $Tag,\
                $FLAVOUR,\
                $HOSTNAME,\
                $IPADDRESS,\
                $UPTIME,\
                "$ACTIVE_KERNEL,\
                $INACTIVE_KERNEL >> $REPORT_FILE

        fi
done < $SOURCE_FILE

Thank you.
 
Last edited:


Hello,

First the way you deal with errors is prone to bugs. You make a first call just to check if you can connect, but if it fails you will still call 6 times a command that won't work. You don't check errors on the following commands but any could fail.

In your errors handling : you are repeating the code. Instead of this simply set a status variable and use it in your output :
Bash:
status_message="successful ssh access"
if [ "$status" == "$UNREACHABLE" ]
       then
              status_message="cannot connect"
...  
      fi

echo "$InputHost,\
$InputIP,\
$status_message,\
$Tag,\
$FLAVOUR,\
$HOSTNAME,\
$IPADDRESS,\
$UPTIME,\
"$ACTIVE_KERNEL,\
$INACTIVE_KERNEL >> $REPORT_FILE

And when it comes to your main question : simply chain your commands with ';' and add a specific delimiter between each command and pass everything in a single ssh request. Then cut the output using your delimiter. You could also reorder your commands so you can use a comma as a delimiter and directly output your ssh output to your report file.
 

Members online


Top