I found a strange error when I try to get SSH Remote command exit code.
I don't understand why it will get different result and how to explain it.
Can someone point out what I'm doing wrong or a better way to capture the exit status of the remote ssh command. Appreciate any help.
local command:
ssh_test/test.sh; echo $?;
+ exit 1
1
ssh command:(Ubuntu 18.04)
ssh 127.0.0.1 "ssh_test/test.sh; echo $?"
+ exit 1
0
test.sh
#!/bin/bash
set -x
exit 1
0 is the exit code being returned from the echo command. If you assign the exit code to a variable this can stop it from being masked with the result of echo.
I should use single quotation marks to double quotation marks.
echo $? will become "0", if I use double quotation marks to execution ssh command.
ssh 127.0.0.1 'ssh_test/test.sh; echo $?'
Related
This question already has answers here:
Exit when one process in pipe fails
(2 answers)
Closed 4 years ago.
Even if the mycode.sh has non-0 exit code this command returns 0 as ssh connection was successful. How to get the actual return code of the .sh on remote server?
/home/mycode.sh '20'${ODATE} 1 | ssh -L 5432:localhost:5432 myuser#myremotehost cat
This is not related to SSH, but to how bash handles the exit status in pipelines. From the bash manual page:
The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled. If pipefail is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully. If the reserved word ! precedes a pipeline, the exit status of that pipeline is the logical negation of the exit status as described above. The shell waits for all commands in the pipeline to terminate before returning a value.
If you want to check that there was an error in the pipeline due to any of the commands involved, just set the pipefail option:
set -o pipefail
your_pipeline_here
echo $? # Prints non-zero if something went wrong
It is not possible to actually send the exit status to the next command in the pipeline (in your case, ssh) without additional steps. If you really want to do that, the command will have to be split like this:
res="$(/home/mycode.sh '20'${ODATE} 1)"
if (( $? == 0 )); then
echo -n "$res" | ssh -L 5432:localhost:5432 myuser#myremotehost cat
else
# You can do anything with the exit status here - even pass it on as an argument to the remote command
echo "mycode.sh failed" >&2
fi
You may want to save the output of mycode.sh to a temporary file instead of the $res variable if it's too large.
/home/mycode.sh is located onto the local host.
the ssh command is running cat on the remote server.
All text printed to the standard output of the /home/mycode.sh is redirected to the cat standard input.
The man ssh reads:
EXIT STATUS
ssh exits with the exit status of the remote command or with 255 if an error occurred.
Conclusion: the ssh exists with the EXIT STATUS of the cat or 255 if an error occurred.
if /home/mycode.sh script prints commands to the standard input, they can be run on the remote server when the cat is not present:
/home/mycode.sh '20'${ODATE} 1 | ssh -L 5432:localhost:5432 myuser#myremotehost
In my test, the EXIT STATUS of the last command executed on the remote server is returned by ssh:
printf "%s\n" "uname -r" date "ls this_file_does_not_exist" |\
ssh -L 5432:localhost:5432 myuser#myremotehost ;\
printf "EXIT STATUS of the last command, executed remotely with ssh is %d\n" $?
4.4.0-119-generic
Wed Aug 29 02:55:04 EDT 2018
ls: cannot access 'this_file_does_not_exist': No such file or directory
EXIT STATUS of the last command, executed remotely with ssh is 2
I am running a script from remote machine via ssh:
ssh 'some_cmd;my_script'
Now, I want to store exit status of shell script on my local machine.
How can I do it?
Assuming nothing goes wrong with ssh itself, its exit status is the exit status of the last command executed on the remote host. (If something does go wrong, its exit status is 255.)
$ ssh remotehost exit 13
$ echo $?
13
I had same problem. I don't think the previous answers will work (at least, they did not work for me).
This is what worked for me: I ran my command and displayed the exit code and captured it in a variable.
Ensure you protect the $? sign with the escape sequence, \:
# retcode=$(ssh test#1.2.3.4 "grep -q test /etc/passwd ; echo \$? " 2>/dev/null)
# echo $retcode
# 1
I am trying to create a bash script that serves as a wrapper for numerous ssh connection options. Basically the user will run the script and the appropriate ssh command will then be created and executed based on their selections. I am trying to find a way to have the script exit and the ssh connection created, rather than having the script continue to run while the user is working on the remote server. Does anyone know if this is possible or how I could achieve this? Thanks!
Edit
Sorry, I should have posted my code:
display_main_menu(){
while true
do
clear
echo ""
echo " Select A Server:"
echo " -------------------------------"
echo " 1) Server 1"
echo " 2) Server 2"
echo " 3) Server 3"
echo " 4) Quit"
local selection
read -p " Enter choice [1 - 4] " selection
case $selection in
1)
# Open SSH Connection to Server 1
break
;;
2)
# Open SSH Connection to Server 2
break
;;
3)
# Open SSH Connection to Server 3
break
;;
4)
exit 0
break
;;
;;
*)
echo -e "Invalid Selection..." && sleep 2
;;
esac
done
}
Use:
exec ssh <pararameters>
The exec builtin command:
Synopsis
exec [-a NAME] [-cl] [COMMAND] [ARG...] [REDIRECTION...]
Description
The exec builtin command is used to
replace the shell with a given program (executing it, not as new
process)
set redirections for the program to execute or for the
current shell
If only redirections are given, the redirections affect the current shell without executing any program.
We have a remote bash shell script on a Linux Server.
We have a local Windows Server 2008 box to use ssh to execute the remote shell script.
We cant seem to get the remote return code.
we tried
ssh remote "./remote_shell.sh test" <-- returns 1
echo %errorlevel%
How do we do it right ?
Thanks
If it's really bash; then the return code is $?
ssh remote "./remote_shell.sh test"
echo $?
ssh remote "./remote_shell.sh test; echo $?"
The echo command will print the exit status of the preceding command. It would be necessary to parse the number from the ssh output. You could make that a little easier by tagging the value:
ssh remote "./remote_shell.sh test; echo exit value was: $?"
I have a Postgres console command createdb appname_production_master, which return error exit code if the database with this name already exists.
Is it possible to make this command do not return any exit code?
Just ignore the exit code, for example like this.
createdb appname_production_master || true
Unix commands always return exit codes, but you need not respond to the exit code.
When you run a command $? is set to the exit code of the process. As this happens for every command, simply running a different command after the first will change $?.
For example:
createdb appname_production_master # returns 1, a failure code
# $? is 1
/bin/true # always returns 0, success
# $? is 0
Here's another example:
/bin/false # returns false, I assume usually 1
echo $? # outputs 1
echo $? # outputs 0, last echo command succeeded