From a bash script I want to run a command which might fail, store its exit code in a variable, and run a subsequent command regardless of that exit code.
Examples of what I'm trying to avoid:
Using set
:
set e # disable exit on error (it was explicitly enabled earlier)
docker exec $CONTAINER_NAME npm test
test_exit_code=$? # remember exit code of previous command
set -e # enable exit on error
echo "copying unit test result file to host"
docker cp $CONTAINER_NAME:/home/test/test-results.xml .
exit $test_exit_code
Using if
:
if docker exec $CONTAINER_NAME npm test ; then
test_exit_code=$?
else
test_exit_code=$?
fi
echo "copying unit test result file to host"
docker cp $CONTAINER_NAME:/home/test/test-results.xml .
exit $test_exit_code
Is there a semantically straightforward way to tell bash "run command without exiting on error, and tell me its exit code"?
CodePudding user response:
I believe you could just use the ||
operator? Which is equivalent to an "if − else" command.
Would the following address your use case? (otherwise feel free to comment!)
set -e # implied in a CI context
exit_status=0
docker exec "$CONTAINER_NAME" npm test || exit_status=$?
docker cp "$CONTAINER_NAME:/home/test/test-results.xml" .
exit "$exit_status"
or more briefly:
set -e # implied in a CI context
docker exec "$CONTAINER_NAME" npm test || exit_status=$?
docker cp "$CONTAINER_NAME:/home/test/test-results.xml" .
exit "${exit_status:-0}"
As an aside, if you are not interested in this exit status code, you can also do something like this:
set -e # implied in a CI context
docker exec "$CONTAINER_NAME" npm test || :
docker cp "$CONTAINER_NAME:/home/test/test-results.xml" .
For more details on the || :
tip, see e.g. this answer on Unix-&-Linux SE:
Which is more idiomatic in a bash script: || true
or || :
?
CodePudding user response:
Very simply save the return-code if command failed:
#!/usr/bin/env sh
# Implied by CI
set -e
# Initialise exit return code
rc=0
# Run command or save its error return code if it fail
docker exec "$CONTAINER_NAME" npm test || rc="$?"
printf '%s\n' "copying unit test result file to host"
# Run other command regardless if first one failed
docker cp "$CONTAINER_NAME:/home/test/test-results.xml" .
# Exit with the return code of the first command
exit "$rc"
CodePudding user response:
You could use a kind of try catch, to get the exit code and use a simple switch case to run another commands depending on the error exit code:
(
exit 2
#here your command which might fail
)
exit_code=$?
case "$exit_code" in
0) echo "Success execution"
#do something
;;
1) echo "Error type 1"
#do something
;;
2) echo "Error type 2"
#do something
;;
*) echo "Unknown error type: $exit_code"
;;
esac