How the value is assigned to the variable with shell script - bash

I have this code but I don't understand it very well.
Can you explain to me how the finish variable gets the value.
what does this assignment "finish=$?" mean?
or if they have any documentation to help me understand.
Thanks in advance.
#!/usr/bin/bash
/usr/bin/java -jar Report.jar $user $pass $base $dateini $datefin $iphost >> file.log 2>&1
finish=$?
if [ $finish -eq 0 ]; then
echo "Report executed successfully" >> file.log
exit 0
else
echo "There was an error in the report" >> file.log
exit 1
fi

The exit status of the last command you ran (/usr/bin/java -jar ...) is stored in the special parameter $?.
Commands executed by the shell script or user have a exit status being either 0 (meaning the command was successful without errors), or a non-zero (1-255) value indicating the command was a failure.
Check here for further information

Related

Should Bash exit 1 show anything on the terminal?

If another script or process, such as the sequential tasks in a Gitlab .gitlab-ci.yml file for instance, depend on a Bash script exiting without an error to continue, or fail to exit further execution; should the Bash script do any thing else than exit 0 for success or exit 1 for catch all errors?
Example code below tests if a site was successfully deployed.
#!/bin/bash
flag="false"
for i in {1..10}
do
response=$(curl -Is http://mysite/ | head -n 1 | tr -d '\r')
echo "$response"
if [ "$response" = "HTTP/1.1 200 OK" ]; then
echo "SITE UP"
flag="true"
exit 0
fi
sleep 1s
done
if [ "$flag" = "false" ]; then
echo "SITE DOWN"
exit 1
fi
Everything works 100% as expected, and the script is executed as ./test-up.sh > /dev/null to suppress the debugging echos used (as well as text returned by the curl command).
However, if the script fails nothing is printed on the command line with regard to errors. The command line stays blank. The same happens if exit 0 was encountered.
Is the above intended?
Echo to stderr
echo "SITE DOWN" >&2

In a bash script, test error code from a called script

My bash script (init.sh) call another script (script.sh) and I want to test the error code from script.sh before doing any further action in init.sh.
I thought about testing it with $?, but it does not work
My init.sh is like the following:
#!/bin/bash
set -e
echo "Before call"
docker run -v $PWD:/t -w /t [command]
if [ $? == 1 ]; then
echo "Issue"
fi
echo "After call"
I only got the Before call from stdout and not the After call.
I know for a fact that if I execute docker run -v $PWD:/t -w /t [command] alone with wrong arguments, then echo $? will rightly display 1.
I was thinking that I do not catch the exit code from scrip.sh, but from somewhere else.
Any ideas?
You running the script with set -e. This means that if any command exits with a non zero status, bash will stop executing all subsequent lines. So here, if docker exits with status 1, the conditional that follows will not have a chance to run at all. Try this instead:
#!/bin/bash
set -e
echo "Before call"
if ! docker run -v $PWD:/t -w /t [command]; then
echo "Issue"
fi
echo "After call"
This runs the command inside the if test which suppresses the effect of set -e I described above and gives you a chance to catch the error. Note this is will also catch all non-zero statuses, not just 1.
Bash numeric comparison operator is -eq, and not ==...
So:
#!/bin/bash
set -e
echo "Before call"
docker run -v $PWD:/t -w /t [command]
if [ $? -eq 1 ]; then
echo "Issue"
fi
echo "After call"
set -e is generally a bad idea. Sure, it may seem like a good idea to have your script exit automatically in the event of an unexpected error, but the problem is that set -e and you may have different ideas about what constitutes a fatal error.
Instead, do your own error handling.
#!/bin/bash
echo "Before call"
docker run -v $PWD:/t -w /t [command]
docker_status=$?
if [ $docker_status != 0 ]; then
echo "docker returned: $docker_status"
exit $docker_status
fi
echo "After call"
In this simple code, I've somewhat redundantly saved the value of $? to another variable first. This ensures that it is preserved after you start executing other commands that examine, log, or otherwise process the value of $?. Also, I'm logging and exiting here on any non-zero status, not just 1. In theory, you might take different action for an exit status of 1 than for an exit status of 2, but here we take the same log-then-exit action for any error.

Calling script from script

How can I have my shell script echo to me that the script that it calls has failed?
#!/bin/sh
test="/Applications/test.sh"
sh $test
exit 0
exit 1
#!/bin/sh
if sh /Applications/test.sh; then
echo "Well done $USER"
exit 0
else
echo "script failed with code [$?]" >&2
exit 1
fi
The /Applications/test.sh script should be well coded to exit with conventional status. 0 if it's ok and > 0 if it fails.
Like you can see, no need to test the special variable $?, we use boolean expression directly.
I usually take the following approach:
#!/usr/bin/env bash
test="/Applications/test.sh"
sh "${test}"
exit_status=$?
if [[ ${exit_status} ]] ; then
echo "Error: ${test} failed with status ${exit_status}." >&2
else
echo "Success!"
fi
In terms of best practice, you should not. If a script fails, it should emit an error message before it terminates so that its parent doesn't have to. The main reason for this is that the process knows why it is failing, while the parent can only guess. In other words, you should just write:
#!/bin/sh
test="/Applications/test.sh"
sh $test
Although really, it would be more typical to just write:
#!/bin/sh
/Applications/test.sh
test.sh will emit the necessary error message, and your script will return the same value as did test.sh. Also, in its current form your script will always be successful, even if test.sh actually failed because exit 0; exit 1 is pretty pointless: the exit 1 will never be called.

Can you access the code of an exit command in a trap?

I understand that I can use $? to see the exit code of the last executed command, but what if I want to identify whether I have thrown my own "exit 0" or "exit 1"?
For example:
#!/bin/bash -e
trap "{ echo Exit code $?; exit; }" EXIT
exit 1
If I run this script, it prints out "Exit code 0" and then exits with exit code 1. Can I access the code in the trap, or am I just going about this the wrong way? In other words, I would like this simple script to print out "Exit code 1".
It's 0 because $? at the beginning of a script, where it is substituted due to the double quotes, is 0.
Try this instead:
trap '{ echo Exit code $?; exit; }' EXIT
Any process that terminates sets the $?, it means that it constantly will get overwritten. Save $? to a separately named var that is unique and echo that upon exit.
Edit
See Exit Shell Script Based on Process Exit Code

Shell scripting: die on any error

Suppose a shell script (/bin/sh or /bin/bash) contained several commands. How can I cleanly make the script terminate if any of the commands has a failing exit status? Obviously, one can use if blocks and/or callbacks, but is there a cleaner, more concise way? Using && is not really an option either, because the commands can be long, or the script could have non-trivial things like loops and conditionals.
With standard sh and bash, you can
set -e
It will
$ help set
...
-e Exit immediately if a command exits with a non-zero status.
It also works (from what I could gather) with zsh. It also should work for any Bourne shell descendant.
With csh/tcsh, you have to launch your script with #!/bin/csh -e
May be you could use:
$ <any_command> || exit 1
You can check $? to see what the most recent exit code is..
e.g
#!/bin/sh
# A Tidier approach
check_errs()
{
# Function. Parameter 1 is the return code
# Para. 2 is text to display on failure.
if [ "${1}" -ne "0" ]; then
echo "ERROR # ${1} : ${2}"
# as a bonus, make our script exit with the right error code.
exit ${1}
fi
}
### main script starts here ###
grep "^${1}:" /etc/passwd > /dev/null 2>&1
check_errs $? "User ${1} not found in /etc/passwd"
USERNAME=`grep "^${1}:" /etc/passwd|cut -d":" -f1`
check_errs $? "Cut returned an error"
echo "USERNAME: $USERNAME"
check_errs $? "echo returned an error - very strange!"

Resources