简体   繁体   中英

Exit subshell on error

I am currently using something like this:

(
false
true 
) && echo "OK" || echo "FAILED";

And it doesn't work. I would like the subshell to exit with an error if something fails (false in this case). Currently it only fails if the last command fails.

It should only exit out of the current subshell and not the whole script.

I am giving this script to people and I don't want them to see all the output but still give them some kind of response if the script was successful or not.

Edit: The commands inside the subshell above are only an example. I would like to run multiple commands inside a subshell without checking the return value after each command . Something like set -e for subshells.

Edit2: I tried adding set -e inside a subshell. Maybe I did something wrong but it didn't change the behavior of my script. It didn't stop execution or exit out of the subshell with a non-0 code.

(
set -e
false
echo "test"
) && echo "OK" || echo "FAILED"; 

First prints test and then OK. It should print FAILED because of false.

To your edited question:

Something like set -e for subshells.

Well, you can just do set -e for the subshell.

( set -e
my
commands
)

You can't implicitly make just your subshells have the errexit option. You can do some trickery using eval , or use a subprocess as a shell (even though a subprocess is not the same as a subshell), like

errexit_shell() {
    bash -e
}

but those options are both inadvisable for various reasons, not the least of which being readability. Your best bet in that case would just be to adapt your entire script to use set -e , and your subshells will come along for the ride.

To your original question:

Just capture the status of the part that indicates success or failure:

(
    cat teisatrt
    status=$?
    echo "true"
    exit "$status"
) && echo passed || echo failed

(Of course, if all you want to know is if that file is readable, don't cat it, just use test -r .)

This effect of bash set -e inside a conditional expression like foo || true foo || true , is known and considered a problem. I think it is good reason to hate both set -e and shell scripting in general.

The first link makes the following suggestion. It looks good in small examples, but maybe less clear in the real world.

Do your own error checking by stringing together a series of commands with “&&” like this:

 mkdir abc && cd abc && do_something_else && last_thing || { echo error >&2; exit 1; } 

A few important notes: You don't need a trailing backslash. You don't indent the following line. You must stick to 80 chars per line so that everyone can see the “&&” or “||” at the end. If you need to mix ANDs and ORs, group with { these braces } which don't spawn a sub-shell.

As you have it, you are redirecting output from the whole subshell to /dev/null, so you will never see your "true" echo. You should move the redirect inside the subshell to the command you really want it on. In order to exit the subshell when cat fails, you will need to check for failure after cat runs. If you don't, then as you have noted, its return code is wiped out by the following statement. So something like this:

echo "Installing App"
(
cat teisatrt &> /dev/null || exit 1
echo "true"
) && echo "OK" || echo "FAILED";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM