Put it in a variable first and then try to test it, as shown below
ret=$?
if [ $ret -ne 0 ]; then
echo "In If"
else
echo "In Else"
fi
This should help.
Edit: If the above is not working as expected then, there is a possibility that you are not using $? at right place. It must be the very next line after the command of which you need to catch the return status. Even if there is any other single command in between the target and you catching it's return status, you'll be retrieving the returns_status of this intermediate command and not the one you are expecting.
You don't need to test if $? is not 0. The shell provides && and || so you can easily branch based on implicit result of that test:
some_command && {
# executes this block of code,
# if some_command would result in: $? -eq 0
} || {
# executes this block of code,
# if some_command would result in: $? -ne 0
}
You can remove either branch, depending on what you want. So if you just want to test for failure (i.e. $? -ne 0):
some_command_returning_nonzero || {
# executes this block of code when: $? -ne 0
# and nothing if the command succeeds: $? -eq 0
}
However, the code you provided in the question works, as is. I'm confused that you got syntax errors & concluded that $? was a string. It's most likely that the errant code causing the syntax error was not provided with the question. This is especially evident because you claim that no one else's solutions work either. When this happens, you have to re-evaluate your assumptions.
NB: The code above may give confusing results if the code inside the braces returns an error. In that case simply use the if command instead, like this:
if some_command; then
# executes this block of code,
# if some_command would result in: $? -eq 0
else
# executes this block of code,
# if some_command would result in: $? -ne 0
fi
I put together some code that may help to see how return value vs returned strings works. There may be a better way, but this is what I found through testing.
#!/bin/sh
#
# ro
#
pass(){
echo passed
return 0; # no errors
}
fail(){
echo failed
return 1; # has an error
}
t(){
echo true, has error
}
f(){
echo false, no error
}
dv=$(printf "%60s"); dv=${dv// /-}
echo return code good for one use, not available for echo
echo $dv
pass
[ $? -gt 0 ] && t || f
echo "function pass: \$? $?" ' return value is gone'
echo
fail
[ $? -gt 0 ] && t || f
echo "function fail: \$? $?" ' return value is gone'
echo
echo save return code to var k for continued usage
echo $dv
pass
k=$?
[ $k -gt 0 ] && t || f
echo "function pass: \$k $k"
echo
fail
k=$?
[ $k -gt 0 ] && t || f
echo "function fail: \$k $k"
echo
# direct evaluation of the return value
# note that (...) and $(...) executes in a subshell
# with return value to calling shell
# ((...)) is for math/string evaluation
echo direct evaluations of the return value:
echo ' by if (pass) and if (fail)'
echo $dv
if (pass); then
echo pass has no errors
else
echo pass has errors
fi
if (fail); then
echo fail has no errors
else
echo fail has errors
fi
# this code results in error because of returned string (stdout)
# but comment out the echo statements in pass/fail functions and this code succeeds
echo
echo ' by if $(pass) and if $(fail) ..this succeeds if no echo to stdout from function'
echo $dv
if $(pass); then
echo pass has no errors
else
echo pass has errors
fi
if $(fail); then
echo fail has no errors
else
echo fail has errors
fi
echo
echo ' by if ((pass)) and if ((fail)) ..this always fails'
echo $dv
if ((pass)); then
echo pass has no errors
else
echo pass has errors
fi
if ((fail)); then
echo fail has no errors
else
echo fail has errors
fi
echo
s=$(pass)
r=$?
echo pass, "s: $s , r: $r"
s=$(fail)
r=$?
echo fail, "s: $s , r: $r"