0

I'm working on a Bash/expect script to run show commands on multiple networking devices.

To identify the devices there are 2 acceptable options:

  1. IP Address
  2. Hostname -> The IP for this will be grepped from an inventory file.

My code:

#!/bin/bash

echo -e "\033[101mInsert the hostnames then hit Ctrl+D\033[0m"
cat > /temp.txt
echo
echo -e "\033[105mInsert the commands then hit Ctrl+D\033[0m"
cat > /commands.txt
echo
read -r -p $'\033[100mChoose what kind of check you would like to perform (\033[92mpre\033[39m or \033[35mpost\033[39m):\033[0m\n' prepost
prepost=${prepost:-pre}

username="uuuuuu"
pass="passssss"

############# Generate Expect Script ###########################################

echo "
#!/usr/bin/expect

set timeout 60
set hostname [lindex \$argv 0]
set username [lindex \$argv 1]
set password [lindex \$argv 2]
set send_slow {10 .001}

send_user \"\n#####\n# \$hostname\n#####\n\"

spawn ssh -oStrictHostKeyChecking=no \$username@\$hostname

expect {
    timeout { send_user \"\nFailed to get password prompt\n\"; exit 1 }
    eof { send_user \"\nSSH failure for \$hostname\n\"; exit 1 }
    \"*#\" {}
    \"*assword:\" {
        send \"\$password\r\"
    }
}

expect {
    default { send_user \"\nCould not get into enabled mode. Password problem?\n\"; exit 1 }
    \"*#\" {}
    \"*>\" {
        send \"ena\r\"
        expect \"*assword\"
        send \"\$password\r\"
    }
}
expect \"*#\"
send \"term len 0\r\"
" >> /generated_expect

while read -r command
do
    echo "
send \"$command\r\"
expect \"*#\"
    " >> /generated_expect
done < /commands.txt

echo "expect \"*#\"
send \"!\r\"
send \"exit\r\"
close
" >> /generated_expect

chmod 700 /generated_expect

############################################################################################

echo
echo "#################################################################################"
echo

while read -r line
do
    match=$(grep -i -m 1 "$line" /inventory.csv | cut -f1 -d";")
    pattern="[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"
    if [[ $line =~ $pattern ]]; then
        host="$line"
        echo Logging into "$host"
        nohup /generated_expect "$host" "$username" "$pass" >> /"$line"_"$prepost".txt
        echo
        echo -e "\033[42m\033[30m        Output successfully collected\033[39m\033[0m        \n"
        echo "--------------------------------------------------------------------------------"
    else
        if [[ $match =~ $line ]]; then
            host=$(grep -i -m 1 "$line" /inventory.csv | cut -f2 -d";")
            hostname=$(grep -i -m 1 "$line" /inventory.csv | cut -f1 -d";")
            echo Logging into "$hostname"
            nohup /generated_expect "$host" "$username" "$pass" >> /"$line"_"$prepost".txt
            echo
            echo -e "\033[42m\033[30m        Output successfully collected\033[39m\033[0m        \n"
            echo "--------------------------------------------------------------------------------"
        else
            echo 0 match found for "$line"
        fi
    fi

done < /temp.txt
echo

rm /temp.txt
rm /commands.txt
rm /generated_expect

I've migrated this script from Ubuntu - where it was working perfectly - to my Mac.

This is the error I'm getting:

#####
# 1.1.1.1
#####
spawn ssh -oStrictHostKeyChecking=no uuuuuu@1.1.1.1
ssh: Could not resolve hostname 1.1.1.1^M: nodename nor servname provided, or not known

SSH failure for 1.1.1.1

I suspected that it has to do with line ending somewhere, but I cannot find it... I've checked everything, twice.

I know that the script itself if not the most elegant way to achieve the task I'm trying to do, but it was working good enough before. Any suggestion would be appreciated.

--- UPDATE ---

I've used ShellCheck as suggested; was able to clean the code a bit, but the error remans the same. I've even tried the sed -i "" 's/\r$//' script.sh which was suggested, but no luck there either.

vikdean
  • 23
  • 1
  • 5
  • 1
    Btw.: Please paste your script at [shellcheck.net](http://www.shellcheck.net/) and try to implement the recommendations made there. – Cyrus Feb 13 '21 at 17:42
  • `sed -i "" 's/\r$//' script.sh` will remove carriage returns at the end of each line. – glenn jackman Feb 13 '21 at 23:06
  • Done the ShellCheck, but no luck, error remains the same. – vikdean Feb 15 '21 at 10:07
  • embedding Expect scripts in shell is kind of messy. Take a look at my [sexpect (Expect for Shells)](https://github.com/clarkwang/sexpect) which you can use to write Expect scripts with **shell code only**. – sexpect - Expect for Shells Feb 18 '21 at 12:54

0 Answers0