Bash Command Nested conditional statements failing, but why - bash

I have a bash script that runs many conditional statements, but when I run the script, it only hits the following line: if [ $? -eq 0 ]
touch /tmp/converted.json
tool test --json --all-projects | tee >> /tmp/converted.json
ret=$?
set -o pipefail
#no vulns
if ((ret == 0)); then
echo "Hooray!"
#found vulns
elif ((ret == 1)); then
then
#check single project
if [[ $firstchar == "{" ]]
then
echo "SINGLE PROJECT"
elif [[ $firstchar == "[" ]]
then
echo "MULTIPROJECT"
else
echo "didnt get a single or multiproject"
fi
#error with your command
elif ((ret == 2)); then
then
echo "An error occurred"
#no manifest
elif ((ret == 3)); then
then
echo "Ensure your repo has a proper required manifest file"
else
echo "Something else occurred"
fi
Thus, why does this continue to hit if((ret==0)) condition?
Thanks

$? has the exit status of the last command executed. The last command at elif [ $? -eq 1 ] was [ executed at if [ $? -eq 0 ].
if [ $? -eq 0 ] # executes `[`
then
: dont care
elif [ $? -eq 1 ] # $? here has a nonzero the exit status of `[`
Just save the exit status to a variable before calling any command right after executing the command you are interested in. In bash you may use arithmetic expansion ((...)).
some_command
ret=$?
if ((ret == 0)); then
: dont care
elif ((ret == 1)); then

Related

How do you cause a script to exit early if there is a syntax issue inside `if [ ]`?

This will cause the script to halt as expected, because grep a b returns a non-zero exit code and the -e option is set:
#!/bin/bash
set -e
grep a b
echo "hi"
$ ./test.sh
grep: b: No such file or directory
However, this doesn't, even though there is a syntax error:
#!/bin/bash
set -e
if [ $a = 'a' ]; then
echo "true"
else
echo "false"
fi
echo "hi"
$ ./test.sh
./test.sh: line 5: [: a: binary operator expected
false
hi
Is there a way to halt the script if there is an issue with the syntax passed to if [ ]?
How do you cause a script to exit early if there is a syntax issue inside if [ ]?
You implement such functionality. Happily it is detectable - test or [ exits with 0 when the expression is true, 1 when the expression is false, but a different exit status is returned when the arguments could not be parsed by test. See posix test EXIT STATUS for reference.
if [ invalid; then
echo ok
else
ret=$?
if ((ret == 1)); then
echo "It was false"
else
echo "Och nuuu - invalid"
exit
fi
fi
or you could write your own function wrapper:
# Fun fact: yes `[` is allowed in function names.
# Many other characters are allowed too.
safe[() {
local ret
ret=0
[ "$#" || ret=$?
if ((ret == 0 || ret == 1)); then
return "$ret"
else
exit 1
fi
}
if safe[ some expression to check ]; then
echo 'it is true!'
else
echo 'it is false!'
fi
You can handle this case using compound commands.
Here is your script using that :
#!/bin/bash
set -e
[ $a = "a" ] && echo "true" || { [ $? != 2 ] && echo "false" || false; }
echo "hi"
If there's a wrong syntax when evaluating the initial [] expression, the return value will be 2 and not 1. With that, you can check when [] fails for syntax reason and force the script to halt with false under set -e.
If the syntax is right, it is then a classic if/then/else in the ternary form.

Not exiting from shell script

I am trying to stop processing a shell script with an IF condition.
output7=${output7##*[[:space:]]}
if [[ $output4 -gt 0 && $output5 -gt 0 && $output6 -gt 0 && $output7 -gt 0 ]]
then echo 'Success'
else echo 'Failure'|| exit 0
fi
echo 'Process Completed'
It is printing the following message but the next statement is also being executed. The output is:
Failure
Process Completed
Can anyone pls tell me why it is not exiting the script.
The problem here is that you are saying that "if echo 'Failure' fails, then exit 0", which is not what you want. You'll want
echo 'Failure'
exit 1
instead. Idiomatic Bash style for the whole section would be:
if [[ $output4 -gt 0 ]] && [[ $output5 -gt 0 ]] && [[ $output6 -gt 0 ]] && [[ $output7 -gt 0 ]]
then
echo 'Success'
else
echo 'Failure'
exit 1
fi

How can I perform an if/else using the shorthand form within a Bash string?

Without having to type out another block of if/else statements, how can I accomplish this within the string?
I want to avoid having to set the wording based on the boolean. The output from the script takes in cronjob_status as a boolean, which in turns does things based on the true/false value. I need to perserve the boolean that's being passed in via stdin for cronjob_status and I want to print the correct word.
if [ "${cronjob_status}" == True ]; then
cronjob_status_display = "enable"
else
cronjob_status_display = "disable"
fi
if [ $? -eq 0 ]
then
echo "Successfully ${cronjob_status_display} the cronjob"
else
echo "Could not create cronjob" >&2
fi
Add a short circuit evaluation, &&:
if [ $? -eq 0 ] && [ "${cronjob_status}" == True ]; then
echo "OK"
else
echo "NOT OK" >&2
fi
If you use the bash builtin [[, then this can also be written as :
if [[ $? -eq 0 && ${cronjob_status} == True ]]; then
echo "OK"
else
echo "NOT OK" >&2
fi
As a side note, you don't necessarily need to check the exit status with $?, you can run the command and check at once after that, for example if the command is e.g. /foo/bar, you could do:
if /foo/bar &>/dev/null && [[ ${cronjob_status} == True ]]; then
echo "OK"
else
echo "NOT OK" >&2
fi
You can use:
[[ $cronjob_status == True ]] &&
cronjob_status_display=enable || cronjob_status_display=disable
A one liner:
[[ $? -eq 0 ]] && echo "Successfully ${cronjob_status} the cronjob" || echo "Could not create cronjob" >&2

Daemon service state check. "$?" always returns 0

I have file "sleepdaemon" which launches python program as service
I run this script:
sudo /etc/init.d/sleepdaemon start
but when I check the state $?=0 always
this is how i check
if [ "$?" -eq 0 ]; then
echo "Process is running"
fi
if [ "$?" -eq 1 ]; then
echo "Process is not running"
fi
if [ "$?" -eq 2 ]; then
echo "Process is not running"
fi
What's the problem ?
The value of $? gets reset after every test, so you either need to save it in a variable before testing, or use a case ... esac statement.
sudo returns the result of the command, or 1 if it can't run it. ? is set for EVERY command:
if (( $? == 0 )); then
echo "Process is running"
elif (( $? == 1 )); then
echo "Process is not running" >&2
elif (( $? == 2 )); then
echo "Process is not running" >&2
else
echo "Unknown exit code $?" >&2
fi
Use (( ... )) for arithmetic comparisons - it is easier and safer. You should always have a default long-stop, and you should report errors to stderr, not stdout.
If $? is always zero, then check the documentation for sleepdaemon (I tried, but can't find a return code documented anywhere).

bash : Illegal number

When I run this bash script :
if [ [$EUID -ne 0] ]; then
echo "This script must be run as root" 1>&2
exit 1
else
printf " whathever "
exit 0
fi
I have this error :
./myScript: 15: [: Illegal number: [
Do you see any problem ?
You have syntax error in your if condition, use this if condition:
if [ "$EUID" -ne 0 ];
OR using [[ and ]]
if [[ "$EUID" -ne 0 ]];
You have syntax error in your if condition, use this if condition:
if [ "$EUID" -ne 0 ];
OR using [[ and ]]
if [[ "$EUID" -ne 0 ]];
If you use the KSH88+/Bash 3+ internal instruction [[, it's not necessary to use doubles quotes around the variables operands :
[ ~/test]$ [[ $var2 = "string with spaces" ]] && echo "OK" || echo "KO"
OK
Instead of the external command test or his fork [ :
[ ~/test]$ [ $var2 = "string with spaces" ] && echo "OK" || echo "KO"
bash: [: too many arguments
KO
[ ~/test]$ [ "$var2" = "string with spaces" ] && echo "OK" || echo "KO"
OK
Of course, you also have to choose the operators according to the type of operands :
[ ~/test]$ var1="01"
[ ~/test]$ [ "$var1" = "1" ] && echo "OK" || echo "KO"
KO
[ ~/test]$ [ "$var1" -eq "1" ] && echo "OK" || echo "KO"
OK
two suggestions apart from what everyone else has pointed out already.
rather than doing else [bunch of code because we are root] fi, just replace the else with fi. once you've tested for the failure condition you are concerned about and taken appropriate action, no need to continue to be within the body of the conditional.
$EUID is a bashism, if you would like to make this portable to shells such as ksh, replacing it with:
if [ $(id -u) -ne 0 ]; then echo "ur not root bro"; exit 1; fi
would be a good way to do it.
using
sudo bash shell_script.sh
instead of
sudo sh shell_script.sh
solved in my case.

Resources