Link to home
Start Free TrialLog in
Avatar of enthuguy
enthuguyFlag for Australia

asked on

Shell script to handle SSH return value

HI,
I perform SSH to a remove linux server with a private key. Since I have a large pool of servers to ssh. I have also have two private keys used by these servers. but only subset uses the 2nd private key.

My request now is
I would like to add a logic in my calling shell script... if ssh failed with below error. Try with the 2nd private key. please help
Guessing, should handle the return code and determine to use 2nd key.

Permission denied (publickey,keyboard-interactive)

Open in new window


and this is how I connect
ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem  ec2-user@${targetIP}

Open in new window

Avatar of enthuguy
enthuguy
Flag of Australia image

ASKER

I tried below if block, but it enters only on success scenario. when exception its not even entering if block

ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem  ec2-user@${targetIP}
if [ "$?" != "0" ]; then
 ssh -o StrictHostKeyChecking=no -i ~/.ssh/secondkey.pem  ec2-user@${targetIP}
fi

Open in new window

@enthuguy

I have written sample script at my system:
cat 29176838.sh
#/bin/bash
targetIP=123.456.78.910
USERNAME=root
ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem  $USERNAME@${targetIP} "pwd;if [ \"\$?\" != \"0\" ];
then
        echo \"Using: ssh -o StrictHostKeyChecking=no -i ~/.ssh/secondkey.pem  $USERNAME@${targetIP}\";
        ssh -o StrictHostKeyChecking=no -i ~/.ssh/secondkey.pem  $USERNAME@${targetIP} \"pwd\";
else
        echo else;
fi"
ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem  $USERNAME@${targetIP} "/usr/bin/pwd"

Open in new window

a)
We need to use \" when we are using any quote.
Example1:
$ /usr/bin/ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem murugesandins@123.456.78.910 "pwd"
/home/murugesandins

Open in new window

After using a command we can use \$? to validate if previous command executed successfully or not
Example1:
$ /usr/bin/ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem murugesandins@123.456.78.910 "ls -ld asd >/dev/null 2>&1;if [ 0 -ne \$? ];then echo asd file not found;fi"
asd file not found

Open in new window

We have to use \$? when passing parameter to ssh
other wise $? from localhost will be passed to remote host.
Example3:
$ /usr/bin/ls -ld delete.txt
/usr/bin/ls: delete.txt: No such file or directory
$ /usr/bin/ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem murugesandins@123.456.78.910 "echo \"Value of => $? passed from localhost at remote host\""
Value of => 2 passed from localhost at remote host
$ /usr/bin/ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem murugesandins@123.456.78.910 "echo \"Value of => $? passed from localhost at remote host\""
Value of => 2 passed from localhost at remote host
$ /usr/bin/ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem murugesandins@123.456.78.910 "echo \"Value of => $? passed from localhost at remote host\""
Value of => 0 passed from localhost at remote host

Open in new window

Value of => 2 passed from localhost at remote host
referring return value of $? due to delete.txt
Use \" when using doublt quotes from ssh
@enthuguy

Sample version0.1 script output:
$ cat ./29176838.sh
#/bin/bash
targetIP=123.456.78.910
USERNAME=root
#Change USERNAME as per your requirement
#Change targetIP as per your requirement
ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem  $USERNAME@${targetIP} "ls NotFound.txt >/dev/null 2>&1;if [ \"$?\" != \"0\" ];
then
        echo \"Using: ssh -o StrictHostKeyChecking=no -i ~/.ssh/secondkey.pem  $USERNAME@${targetIP}\";
        ssh -o StrictHostKeyChecking=no -i ~/.ssh/secondkey.pem  $USERNAME@${targetIP} \"pwd\";
else
        echo else;
fi"
ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem  $USERNAME@${targetIP} "pwd"
$ ./29176838.sh
else
/home/murugesandins/experts_exchange

Open in new window



I updated that code again
$ cat ./29176838.sh
#/bin/bash
targetIP=123.456.78.910
USERNAME=root
#Change USERNAME as per your requirement
#Change targetIP as per your requirement
ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem  $USERNAME@${targetIP} "ls NotFound.txt >/dev/null 2>&1;if [ \"\$?\" != \"0\" ];
then
        echo \"Using: ssh -o StrictHostKeyChecking=no -i ~/.ssh/secondkey.pem  $USERNAME@${targetIP}\";
        ssh -o StrictHostKeyChecking=no -i ~/.ssh/secondkey.pem  $USERNAME@${targetIP} \"pwd\";
else
        echo else \$Ret;
fi"
$ ./29176838.sh
Using: ssh -o StrictHostKeyChecking=no -i ~/.ssh/secondkey.pem  root@123.456.78.910
/home/murugesandins/experts_exchange

Open in new window

Avatar of David Favor
You code should work.

Try changing to this...

ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem  ec2-user@${targetIP}
res=$?
echo "# res: $res"
if [ "$res" != "0" ]; then
 ssh -o StrictHostKeyChecking=no -i ~/.ssh/secondkey.pem  ec2-user@${targetIP}
fi

Open in new window


See what the actual value of $res might be. For failures, normally you'll see a non-zero error code.
Thanks so much murugesandins, that was very details. Really appreciate your time

Just wanted to provide the actual script syntax I execute. Do you think, I can still use dev/null. please help

ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem  ec2-user@${targetIP} 'bash -s' < ${scriptsHome}/dummy.sh "\"${var2}\" \"${var1}\" \"${type}\" \"${NasRemotePath}\" \"${var3}\""

Open in new window

@enthuguy

Can you describe your requirement in detail?

I am not sure about your requirement:
#!/bin/bash
targetIP=123.456.78.910
USERNAME=murugesandins
ssh -o StrictHostKeyChecking=no -i ~/.ssh/firstkey.pem  ${USERNAME}@${targetIP} 'if [ -z "${scriptsHome}" ];\
then
	scriptsHome=/home/murugesandins
fi
if [ -f ${scriptsHome}/dummy.sh ]
then
	if [ -z "${var2}" ]
	then
		var2="hai2"
	fi
	if [ -z "${var1}" ]
	then
		var1="hai1"
	fi
	if [ -z "${var3}" ]
	then
		var3="hai3"
	fi
	if [ -z "${type}" ]
	then
		type="type"
	fi
	if [ -z "${NasRemotePath}" ]
	then
		NasRemotePath="NasRemotePath"
	fi
	echo "Output after executing following command:"
	echo ${scriptsHome}/dummy.sh "\"${var2}\" \"${var1}\" \"${type}\" \"${NasRemotePath}\" \"${var3}\""
	${scriptsHome}/dummy.sh "\"${var2}\" \"${var1}\" \"${type}\" \"${NasRemotePath}\" \"${var3}\""
fi'

Open in new window

Sample output:
$ ./29176838_version2.sh
Output after executing following command:
/home/murugesandins/dummy.sh "hai2" "hai1" "type" "NasRemotePath" "hai3"
/home/murugesandins
"hai2" "hai1" "type" "NasRemotePath" "hai3"

Open in new window


$ cat /home/murugesandins/dummy.sh
#!/bin/bash
pwd
echo $@

Open in new window


Replace 123.456.78.910 murugesandins to required IP/username
ASKER CERTIFIED SOLUTION
Avatar of MURUGESAN N
MURUGESAN N
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you and welcome.
Let us know if having further statement at current query ?
I think your problem may be that ssh is trying your first identity file, and if it fails, prompting for a password.

To avoid this, by forcing the use of the identity file, set the ChallengeResponseAuthentication and PasswordAuthentication options to no. I also do a trial run, by adding the "-n" option - this doesn't try to run a remote command, just connects and disconnects again. It allows me to work out which key worked, and to use that later to run the actual remote command you are trying to run. I report an error if neither key worked (also if the remote host was down).

VALID_KEY=""
ssh -n -o StrictHostKeyChecking=no -o ChallengeResponseAuthentication=no -o PasswordAuthentication=no -i ~/.ssh/firstkey.pem  ec2-user@${targetIP}
if [ $? -eq 0 ]; then
    VALID_KEY=firstkey.pem
else
    ssh -n -o StrictHostKeyChecking=no -o ChallengeResponseAuthentication=no -o PasswordAuthentication=no -i ~/.ssh/secondkey.pem  ec2-user@${targetIP}
    if [ $? -eq 0 ]; then
        VALID_KEY=secondkey.pem
    fi
fi
if [ ${VALID_KEY} ]; then
  # Here do the actual ssh command you want to use (where I have "remote_command")
  ssh -o StrictHostKeyChecking=no -i ~/.ssh/${VALID_KEY} ec2-user@${targetIP} remote_command
else
  echo "ERROR: No valid key found for host ${targetIP}" 1>&2
fi

Open in new window


Couple of extra changes. I've used the mathematical test for the response ($? -eq 0) rather than the string test (!=) you used. We *know* that $? will be a number! Also the "1>&2" will redirect the standard output of the "echo" command to standard error.

Edit: Forgot the "-n" options on the two "test" ssh calls! There shouldn't be one on the last call, since that one *does* want to do work on the remote host.
One other thing. Is the original code you posted exactly as run? *Any* command (even an "echo") between the "ssh" and the "if" will overwrite the return code from the ssh. If you want to test a return code, the best thing is to store it in a variable in the line immediately after the command.
Thanks all
You're welcome!

Good luck!
$ echo wELcOME | /usr/bin/wc >/dev/null