`exitFailure` gives zero exit code - exit-code

I'd expect exitFailure
Exit the program indicating failure.
to give a non-zero exit code, but the program
main : IO ()
main = exitFailure
results in
$ idris2 Foo.idr -x main
$ echo $?
0
What have I misunderstood?

Related

Variable definition are separate from assignment in bash [duplicate]

This Bash snippet works as expected:
$ fun1() { x=$(false); echo "exit code: $?"; }
$ fun1
exit code: 1
But this one, using local, does not as I would have expected:
$ fun2() { local x=$(false); echo "exit code: $?"; }
$ fun2
exit code: 0
Can anyone explain why does local sweep the return code of the command?
The reason the code with local returns 0 is because $? "Expands to the exit status of the most recently executed foreground pipeline." Thus $? is returning the success of local
You can fix this behavior by separating the declaration of x from the initialization of x like so:
$ fun() { local x; x=$(false); echo "exit code: $?"; }; fun
exit code: 1
The return code of the local command obscures the return code of false

Exit code of traps in Bash

This is myscript.sh:
#!/bin/bash
function mytrap {
echo "Trapped!"
}
trap mytrap EXIT
exit 3
And when I run it:
> ./myscript.sh
echo $?
3
Why is the exit code of the script the exit code with the trap the same as without it? Usually, a function returns implicitly the exit code of the last command executed. In this case:
echo returns 0
I would expect mytrap to return 0
Since mytrap is the last function executed, the script should return 0
Why is this not the case? Where is my thinking wrong?
Look the reference from the below man bash page,
exit [n]
Cause the shell to exit with a status of n. If n is omitted, the exit status is that of the last command executed. A trap on EXIT is executed before the shell terminates.
You have the debug version of the script to prove that,
+ trap mytrap EXIT
+ exit 3
+ mytrap
+ echo 'Trapped!'
Trapped!
Consider the same as you mentioned in your comments, the trap function returning an error code,
function mytrap {
echo "Trapped!"
exit 1
}
Look the expanded version of the script,
+ trap mytrap EXIT
+ exit 3
+ mytrap
+ echo 'Trapped!'
Trapped!
+ exit 1
and
echo $?
1
To capture the exit code on trap function,
function mytrap {
echo "$?"
echo "Trapped!"
}

BASH Multiple on-exit functions for different exit levels

How can I use multiple on-exit traps in bash?
say i want to run on-exit-1 on exit code 1
and on-exit-2 on exit code 2
function on-exit1 {
echo "do stuff here if code had exit status 1"
}
function on-exit2 {
echo "do stuff here if code had exit status 2"
}
.....
trap on-exit1 EXIT # <--- what do i do here to specify the exit code to trap
trap on-exit2 EXIT # <--- what do i do here to specify the exit code to trap
.....
some bashing up in here
blah...blah
exit 1 # do on-exit1
else blah blah
exit 2 # do on-exit2
else blah blah
exit N # do on-exitNth
Something like the following code sample should work :
exit_check () {
# bash variable $? contains the last function exit code
# will run the function on_exit1 if status exit is 1, on_exit2 if status exit is 2, ...
on_exit$?
}
trap exit_check EXIT
If you really want to use Traps, try this:
#!/usr/bin/env bash
function finish {
echo "exitcode: $?"
}
trap finish EXIT
read -n 1 -s exitcode
exit $exitcode
But as #123 suggested, you could just call your exit functions, no need to 'abuse' Traps here.
Try to provide working a working example next time ;).

Handling exit code returned by python in shell script

I am calling a python script from within a shell script. The python script returns error codes in case of failures.
How do I handle these error codes in shell script and exit it when necessary?
The exit code of last command is contained in $?.
Use below pseudo code:
python myPythonScript.py
ret=$?
if [ $ret -ne 0 ]; then
#Handle failure
#exit if required
fi
You mean the $? variable?
$ python -c 'import foobar' > /dev/null
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named foobar
$ echo $?
1
$ python -c 'import this' > /dev/null
$ echo $?
0
Please use logic below to process script execution result:
python myPythonScript.py
# $? = is the exit status of the most recently-executed command; by convention, 0 means success and anything else indicates failure.
if [ $? -eq 0 ]
then
echo "Successfully executed script"
else
# Redirect stdout from echo command to stderr.
echo "Script exited with error." >&2
fi

return value from subshell and output to local variables

I've found the strange behaviour for me, which I can't explain.
The following code is work OK:
function prepare-archive {
blah-blah-blah...
_SPEC_FILE=$(check-spec-file "$_GIT_DIR/packaging/")
exit $?
blah-blah-blah...
}
means I get value which I expect:
bash -x ./this-script.sh:
++ exit 1
+ _SPEC_FILE='/home/likern/Print/Oleg/print-service/packaging/print-service.spec
/home/likern/Print/Oleg/print-service/packaging/print-service2.spec'
+ exit 1
As soon as I add local definition to variable:
local _SPEC_FILE=$(check-spec-file "$_GIT_DIR/packaging/")
I get following:
bash -x ./this-script.sh:
++ exit 1
+ local '_SPEC_FILE=/home/likern/Print/Oleg/print-service/packaging/print-service.spec
/home/likern/Print/Oleg/print-service/packaging/print-service2.spec'
+ exit 0
$:~/MyScripts$ echo $?
0
Question: Why? What has happened? Can I catch output from subshell to local variable and check subshell's return value reliably?
P.S.: prepare-archive is called in the main shell script. The first exit is the exit from check-spec-file function, the second from prepare-archive function - this function itself is executed from main shell script. I return value from check-spec-file by exit 1, then pass this value to exit $?. Thus I expect they should be the same.
To capture subshell's exit status, declare the variable as local before the assignment, for example, the following script
#!/bin/sh
local_test()
{
local local_var
local_var=$(echo "hello from subshell"; exit 1)
echo "subshell exited with $?"
echo "local_var=$local_var"
}
echo "before invocation local_var=$local_var in global scope"
local_test
echo "after invocation local_var=$local_var in global scope"
produces the following output
before invocation local_var= in global scope
subshell exited with 1
local_var=hello from subshell
after invocation local_var= in global scope
From the bash manual, Shell Builtin Commands section:
local:
[...]The return status is zero unless local is used outside a function, an invalid name is supplied, or name is a readonly variable.
Hope this helps =)
As I use bash subshell parenthesis to group many echo commands I hit this strange problem.
In my case all I needed was to pass one value back to the calling shell so I just used the exit command
RET=0
echo RET: $RET
(echo hello
echo there
RET=123
echo RET: $RET
exit $RET)
RET=$?
echo RET: $RET
gives the following output
RET: 0
hello
there
RET: 123
RET: 123
without the exit command you will get this which is confusing:
RET: 0
hello
there
RET: 123
RET: 0

Resources