How to return exit code 0 from a failed command
Simply append return 0
to the function to force a function to always exit successful.
function a() {
ls aaaaa 2>&1
return 0
}
a
echo $? # prints 0
If you wish to do it inline for any reason you can append || true
to the command:
ls aaaaa 2>&1 || true
echo $? # prints 0
If you wish to invert the exit status simple prepend the command with !
! ls aaaaa 2>&1
echo $? # prints 0
! ls /etc/resolv.conf 2>&1
echo $? # prints 1
Also if you state what you are trying to achieve overall we might be able to guide you to better answers.
bash execute whole script but return exit code 0 if any intermediate job has failed
You can trap errors:
#!/bin/bash
echo "test start."
trap 'rc=$?' ERR
./error.sh
./script2.sh
echo "test done."
return ${rc}
For more information on how traps work, see trap.
How to make the sh script return an error code from the executed command?
Just do:
#!/bin/sh
pppd call "${@:-provider}" || exit
...
or
if pppd call "${@:-provider}"; then : ; else exit; fi
If pppd
fails, the script will exit and the value it returns will be that returned by pppd. (You could explicitly write exit $?
, but that is the default value returned by exit when no argument is given and is not necessary.) If pppd
succeeds, the script will continue.
The problem with your script (other than the ill-advised usage of exec
, which I will mostly ignore) is that calling [ $? -ne 0 ]
resets $?
. You could re-write your script as:
#!/bin/sh
pppd call "${@:-provider}"
save_val=$?
if ! [ $save_val -eq 0 ]
then
exit $save_val
fi
but that seems excessively verbose.
Note that in your original script, you would get an error on the line if [ $? !-eq 0 ]
, since !-eq
is not a valid operator. However, you never see that error because your early invocation of exec
makes it so that line is never executed.
python subprocess with failed command return code 0
Running the shell command (equivalent to your given subprocess.Popen()
call if we disregard the use of "smart quotes")
'python' '-c' '"import xxx"'
correctly exits with status 0, whether or not a module named xxx exists.
This is because "import xxx"
is a string, and evaluating a string does not throw an exception. You'd get the exact same behavior from python -c '"hello world"'
, or any other string.
If you really want to try executing the code import xxx
, then you need to remove the extra quotes:
subprocess.Popen(['python', '-c', 'import xxx']).wait()
...will properly return 1
(if no xxx
module exists).
How to exit if a command failed?
Try:
my_command || { echo 'my_command failed' ; exit 1; }
Four changes:
- Change
&&
to||
- Use
{ }
in place of( )
- Introduce
;
afterexit
and - spaces after
{
and before}
Since you want to print the message and exit only when the command fails ( exits with non-zero value) you need a ||
not an &&
.
cmd1 && cmd2
will run cmd2
when cmd1
succeeds(exit value 0
). Where as
cmd1 || cmd2
will run cmd2
when cmd1
fails(exit value non-zero).
Using ( )
makes the command inside them run in a sub-shell and calling a exit
from there causes you to exit the sub-shell and not your original shell, hence execution continues in your original shell.
To overcome this use { }
The last two changes are required by bash.
Consider a specific exit code not a failure and proceed
There are some problems cmd1 || $(($?==253 ? true : false) && cmd2
:
- A
)
is missing afterfalse
. - You don't want
$(( ... ))
but(( ... ))
. The former would execute the result of the expression (that is a number!) as a command. The latter just evaluates the expression and fails if the result is 0 and succeeds otherwise. Note that is the opposite of how exit codes work. true
andfalse
are not commands here, but variables. If an undefined variable is used inside(( ... ))
its value is always 0. Therefore the command((... ? true : false))
always fails.
Here is want you could have written instead:
cmd1 || (($?==253 ? 1 : 0)) && cmd2
Test:
prompt$ true || (($?==253 ? 1 : 0)) && echo ok
ok
prompt$ false || (($?==253 ? 1 : 0)) && echo ok
prompt$ ( exit 253; ) || (($?==253 ? 1 : 0)) && echo ok
ok
However, the ternary operator isn't really needed here. The following would be equivalent:
cmd1 || (($?==253)) && cmd2
Despite that, an if
would probably be better. If you don't want to use one inline, you can write a function for that:
# allow all exit codes given as the first argument
# multiple exit codes can be comma separated
allow() {
ok=",$1,"
shift
"$@"
[[ "$ok" = *,$?,* ]]
}
allow 0,253 cmd1 && cmd2
Or define a wrapper just for this one command
cmd1() {
command cmd1 "$@" || (( $? == 253 ))
}
cmd1 && cmd2
Related Topics
Using Curl in a Bash Script and Getting Curl: (3) Illegal Characters Found in Url
How to Use Both 64 Bit and 32 Bit Instructions in the Same Executable in 64 Bit Linux
How to Make a Bash Shell Script Interact with Another Command Line Program
Using Output of Awk to Run Command
Understanding Sendfile() and Splice()
Split Files Based on File Content and Pattern Matching
How to Prevent a Linux User Space Pthread Yielding in Critical Code
How to Forward Localhost Port on My Container to Localhost on My Host
How to Run the Cron Job as a User Instead of Root User
Open a File Directly from a Gitlab Private Repository
Docker Change Cgroup Driver to Systemd
Why Can't I Access Xampp's PHPmyadmin on Localhost? Access Is Forbidden
Scripts Launched from Udev Do Not Have Display Access Anymore