exit shell script from a subshell
Clash Royale CLAN TAG#URR8PPP
Consider this snippet:
stop ()
echo "$1" 1>&2
exit 1
func ()
if false; then
echo "foo"
else
stop "something went wrong"
fi
Normally when func
is called it will cause the script to terminate, which is the intended behaviour. However, if it's executed in a sub-shell, such as in
result=`func`
it will not exit the script. This means the calling code has to check the exit status of the function every time. Is there a way to avoid this? Is this what set -e
is for?
shell shell-script exit subshell
|
show 1 more comment
Consider this snippet:
stop ()
echo "$1" 1>&2
exit 1
func ()
if false; then
echo "foo"
else
stop "something went wrong"
fi
Normally when func
is called it will cause the script to terminate, which is the intended behaviour. However, if it's executed in a sub-shell, such as in
result=`func`
it will not exit the script. This means the calling code has to check the exit status of the function every time. Is there a way to avoid this? Is this what set -e
is for?
shell shell-script exit subshell
1
i want a function "stop" that prints a message to stderr and stops the script, but it doesn't stop when the function that calls stop is executed in a sub-shell, like in the example
– Ernest A C
Sep 18 '12 at 16:41
2
Of course, because it exits from the subshell not the current one. Simply call the function directly:func
.
– user13742
Sep 18 '12 at 16:42
1
i can't call it directly because it returns a string that has to be stored in a variable
– Ernest A C
Sep 18 '12 at 16:53
1
@ErnestAC Please provide all the details in the original question. The above function does not return a string.
– user13742
Sep 18 '12 at 17:03
1
@htor I changed the example
– Ernest A C
Sep 18 '12 at 17:29
|
show 1 more comment
Consider this snippet:
stop ()
echo "$1" 1>&2
exit 1
func ()
if false; then
echo "foo"
else
stop "something went wrong"
fi
Normally when func
is called it will cause the script to terminate, which is the intended behaviour. However, if it's executed in a sub-shell, such as in
result=`func`
it will not exit the script. This means the calling code has to check the exit status of the function every time. Is there a way to avoid this? Is this what set -e
is for?
shell shell-script exit subshell
Consider this snippet:
stop ()
echo "$1" 1>&2
exit 1
func ()
if false; then
echo "foo"
else
stop "something went wrong"
fi
Normally when func
is called it will cause the script to terminate, which is the intended behaviour. However, if it's executed in a sub-shell, such as in
result=`func`
it will not exit the script. This means the calling code has to check the exit status of the function every time. Is there a way to avoid this? Is this what set -e
is for?
shell shell-script exit subshell
shell shell-script exit subshell
edited Sep 18 '12 at 23:50
Gilles
526k12710561580
526k12710561580
asked Sep 18 '12 at 16:36
Ernest A C
229259
229259
1
i want a function "stop" that prints a message to stderr and stops the script, but it doesn't stop when the function that calls stop is executed in a sub-shell, like in the example
– Ernest A C
Sep 18 '12 at 16:41
2
Of course, because it exits from the subshell not the current one. Simply call the function directly:func
.
– user13742
Sep 18 '12 at 16:42
1
i can't call it directly because it returns a string that has to be stored in a variable
– Ernest A C
Sep 18 '12 at 16:53
1
@ErnestAC Please provide all the details in the original question. The above function does not return a string.
– user13742
Sep 18 '12 at 17:03
1
@htor I changed the example
– Ernest A C
Sep 18 '12 at 17:29
|
show 1 more comment
1
i want a function "stop" that prints a message to stderr and stops the script, but it doesn't stop when the function that calls stop is executed in a sub-shell, like in the example
– Ernest A C
Sep 18 '12 at 16:41
2
Of course, because it exits from the subshell not the current one. Simply call the function directly:func
.
– user13742
Sep 18 '12 at 16:42
1
i can't call it directly because it returns a string that has to be stored in a variable
– Ernest A C
Sep 18 '12 at 16:53
1
@ErnestAC Please provide all the details in the original question. The above function does not return a string.
– user13742
Sep 18 '12 at 17:03
1
@htor I changed the example
– Ernest A C
Sep 18 '12 at 17:29
1
1
i want a function "stop" that prints a message to stderr and stops the script, but it doesn't stop when the function that calls stop is executed in a sub-shell, like in the example
– Ernest A C
Sep 18 '12 at 16:41
i want a function "stop" that prints a message to stderr and stops the script, but it doesn't stop when the function that calls stop is executed in a sub-shell, like in the example
– Ernest A C
Sep 18 '12 at 16:41
2
2
Of course, because it exits from the subshell not the current one. Simply call the function directly:
func
.– user13742
Sep 18 '12 at 16:42
Of course, because it exits from the subshell not the current one. Simply call the function directly:
func
.– user13742
Sep 18 '12 at 16:42
1
1
i can't call it directly because it returns a string that has to be stored in a variable
– Ernest A C
Sep 18 '12 at 16:53
i can't call it directly because it returns a string that has to be stored in a variable
– Ernest A C
Sep 18 '12 at 16:53
1
1
@ErnestAC Please provide all the details in the original question. The above function does not return a string.
– user13742
Sep 18 '12 at 17:03
@ErnestAC Please provide all the details in the original question. The above function does not return a string.
– user13742
Sep 18 '12 at 17:03
1
1
@htor I changed the example
– Ernest A C
Sep 18 '12 at 17:29
@htor I changed the example
– Ernest A C
Sep 18 '12 at 17:29
|
show 1 more comment
6 Answers
6
active
oldest
votes
You could kill the original shell (kill $$
) before calling exit
, and that'd probably work. But:
- it seems rather ugly to me
- it will break if you have a second subshell in there, i.e., use a subshell inside a subshell.
Instead, you could use one of the several ways to pass back a value in the Bash FAQ. Most of them aren't so great, unfortunately. You may just be stuck checking for errors after each function call (-e
has a lot of problems). Either that, or switch to Perl.
4
Thanks. I'd rather switch to Python, though.
– Ernest A C
Sep 18 '12 at 18:35
add a comment |
You could decide that the exit status 77 for instance means exit any level of subshell, and do
set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR
(
echo here
(
echo there
(
exit 12 # not 77, exit only this subshell
)
echo ici
exit 77 # exit all subshells
)
echo not here
)
echo not here either
set -E
in combination with ERR
traps is a bit like an improved version of set -e
in that it allows you to define your own error handling.
In zsh, ERR traps are inherited automatically, so you don't need set -E
, you can also define traps as TRAPERR()
functions, and modify them through $functions[TRAPERR]
, like functions[TRAPERR]="echo was here; $functions[TRAPERR]"
1
Interesting solution! Clearly more elegant thankill $$
.
– user13742
Sep 19 '12 at 9:23
2
One thing to watch out for, this trap won't handle interpolated commands, e.g.echo "$(exit 77)"
; the script will carry on as if we'd writtenecho ""
– Warbo
Mar 30 '16 at 14:58
Interresting! Is there any luck on (quite older) bash that doesn't have -E ? maybe we have to resort to defining a trap on a USER signal and using a kill to that signal? I'll do some reasearch too...
– Olivier Dulac
Apr 6 '16 at 18:44
How to know, when not being in a sub-shell trap, in order to return 1 instead of 77?
– ceving
Nov 9 '16 at 14:38
add a comment |
As an alternative to kill $$
, you may also try kill 0
, it will work in the case of nested subshells (all callers and side process will receive the signal) … but it's still brutal and ugly.
2
Wouldn't this kill process id 0?
– Ernest A C
Sep 18 '12 at 18:35
4
That'll kill the entire process group. You may hit things you don't want (if for example you've started some things in the background).
– derobert
Sep 18 '12 at 19:11
2
@ErnestAC see the kill(2) manpage, pids ≤0 have special meaning.
– derobert
Sep 18 '12 at 19:15
add a comment |
Try this ...
stop ()
echo "$1" 1>&2
exit 1
func ()
if $1; then
echo "foo"
else
stop "something went wrong"
fi
echo "shell..."
func $1
echo "subshell..."
result=`func $1`
echo "shell..."
echo "result=$result"
The results I get are ...
# test_exitsubshell true
shell...
foo
subshell...
shell...
result=foo
# test_exitsubshell false
shell...
something went wrong
Notes
- Parameterized to allow the
if
test to betrue
orfalse
(see the 2 runs) - When the
if
test isfalse
, we never reach the subshell.
This is very similar to the original idea the user was posting about and said didn't work. I don't think this works for the subshell case. Your test using false exits after the "shell" case and never gets to the "subshell" test case. I believe it would fail for that case since the subshell would exit from the "exit 1" call but does not propagate the error to the outer shell.
– stuckj
Oct 12 '16 at 17:49
add a comment |
(Bash specific answer)
Bash has no concept of exceptions.
However, with set -o errexit (or the equivalent: set -e) at the outermost level, the failed command will result in the subshell exiting with a non-zero exit status.
If this is a set of nested subshells without conditionals around the execution of those subshells, it will effectively 'roll up' the entire script and exit.
This can be tricky when trying to include bits of various bash code into a larger script. One chunk of bash may work just fine on its own, but when executed under errexit (or without errexit), behave in unexpected ways.
[192.168.13.16 (f0f5e19e) ~ 22:58:22]# bash -o errexit /tmp/foo
something went wrong
[192.168.13.16 (f0f5e19e) ~ 22:58:31]# bash /tmp/foo
something went wrong
But we got here anyways
[192.168.13.16 (f0f5e19e) ~ 22:58:37]# cat /tmp/foo
#!/bin/bash
stop ()
echo "$1"
exit 1
if false; then
echo "foo"
else
(
stop "something went wrong"
)
echo "But we got here anyways"
fi
[192.168.13.16 (f0f5e19e) ~ 22:58:40]#
add a comment |
My example to exit in one liner:
COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f48533%2fexit-shell-script-from-a-subshell%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
You could kill the original shell (kill $$
) before calling exit
, and that'd probably work. But:
- it seems rather ugly to me
- it will break if you have a second subshell in there, i.e., use a subshell inside a subshell.
Instead, you could use one of the several ways to pass back a value in the Bash FAQ. Most of them aren't so great, unfortunately. You may just be stuck checking for errors after each function call (-e
has a lot of problems). Either that, or switch to Perl.
4
Thanks. I'd rather switch to Python, though.
– Ernest A C
Sep 18 '12 at 18:35
add a comment |
You could kill the original shell (kill $$
) before calling exit
, and that'd probably work. But:
- it seems rather ugly to me
- it will break if you have a second subshell in there, i.e., use a subshell inside a subshell.
Instead, you could use one of the several ways to pass back a value in the Bash FAQ. Most of them aren't so great, unfortunately. You may just be stuck checking for errors after each function call (-e
has a lot of problems). Either that, or switch to Perl.
4
Thanks. I'd rather switch to Python, though.
– Ernest A C
Sep 18 '12 at 18:35
add a comment |
You could kill the original shell (kill $$
) before calling exit
, and that'd probably work. But:
- it seems rather ugly to me
- it will break if you have a second subshell in there, i.e., use a subshell inside a subshell.
Instead, you could use one of the several ways to pass back a value in the Bash FAQ. Most of them aren't so great, unfortunately. You may just be stuck checking for errors after each function call (-e
has a lot of problems). Either that, or switch to Perl.
You could kill the original shell (kill $$
) before calling exit
, and that'd probably work. But:
- it seems rather ugly to me
- it will break if you have a second subshell in there, i.e., use a subshell inside a subshell.
Instead, you could use one of the several ways to pass back a value in the Bash FAQ. Most of them aren't so great, unfortunately. You may just be stuck checking for errors after each function call (-e
has a lot of problems). Either that, or switch to Perl.
answered Sep 18 '12 at 17:52
derobert
71.7k8152210
71.7k8152210
4
Thanks. I'd rather switch to Python, though.
– Ernest A C
Sep 18 '12 at 18:35
add a comment |
4
Thanks. I'd rather switch to Python, though.
– Ernest A C
Sep 18 '12 at 18:35
4
4
Thanks. I'd rather switch to Python, though.
– Ernest A C
Sep 18 '12 at 18:35
Thanks. I'd rather switch to Python, though.
– Ernest A C
Sep 18 '12 at 18:35
add a comment |
You could decide that the exit status 77 for instance means exit any level of subshell, and do
set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR
(
echo here
(
echo there
(
exit 12 # not 77, exit only this subshell
)
echo ici
exit 77 # exit all subshells
)
echo not here
)
echo not here either
set -E
in combination with ERR
traps is a bit like an improved version of set -e
in that it allows you to define your own error handling.
In zsh, ERR traps are inherited automatically, so you don't need set -E
, you can also define traps as TRAPERR()
functions, and modify them through $functions[TRAPERR]
, like functions[TRAPERR]="echo was here; $functions[TRAPERR]"
1
Interesting solution! Clearly more elegant thankill $$
.
– user13742
Sep 19 '12 at 9:23
2
One thing to watch out for, this trap won't handle interpolated commands, e.g.echo "$(exit 77)"
; the script will carry on as if we'd writtenecho ""
– Warbo
Mar 30 '16 at 14:58
Interresting! Is there any luck on (quite older) bash that doesn't have -E ? maybe we have to resort to defining a trap on a USER signal and using a kill to that signal? I'll do some reasearch too...
– Olivier Dulac
Apr 6 '16 at 18:44
How to know, when not being in a sub-shell trap, in order to return 1 instead of 77?
– ceving
Nov 9 '16 at 14:38
add a comment |
You could decide that the exit status 77 for instance means exit any level of subshell, and do
set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR
(
echo here
(
echo there
(
exit 12 # not 77, exit only this subshell
)
echo ici
exit 77 # exit all subshells
)
echo not here
)
echo not here either
set -E
in combination with ERR
traps is a bit like an improved version of set -e
in that it allows you to define your own error handling.
In zsh, ERR traps are inherited automatically, so you don't need set -E
, you can also define traps as TRAPERR()
functions, and modify them through $functions[TRAPERR]
, like functions[TRAPERR]="echo was here; $functions[TRAPERR]"
1
Interesting solution! Clearly more elegant thankill $$
.
– user13742
Sep 19 '12 at 9:23
2
One thing to watch out for, this trap won't handle interpolated commands, e.g.echo "$(exit 77)"
; the script will carry on as if we'd writtenecho ""
– Warbo
Mar 30 '16 at 14:58
Interresting! Is there any luck on (quite older) bash that doesn't have -E ? maybe we have to resort to defining a trap on a USER signal and using a kill to that signal? I'll do some reasearch too...
– Olivier Dulac
Apr 6 '16 at 18:44
How to know, when not being in a sub-shell trap, in order to return 1 instead of 77?
– ceving
Nov 9 '16 at 14:38
add a comment |
You could decide that the exit status 77 for instance means exit any level of subshell, and do
set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR
(
echo here
(
echo there
(
exit 12 # not 77, exit only this subshell
)
echo ici
exit 77 # exit all subshells
)
echo not here
)
echo not here either
set -E
in combination with ERR
traps is a bit like an improved version of set -e
in that it allows you to define your own error handling.
In zsh, ERR traps are inherited automatically, so you don't need set -E
, you can also define traps as TRAPERR()
functions, and modify them through $functions[TRAPERR]
, like functions[TRAPERR]="echo was here; $functions[TRAPERR]"
You could decide that the exit status 77 for instance means exit any level of subshell, and do
set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR
(
echo here
(
echo there
(
exit 12 # not 77, exit only this subshell
)
echo ici
exit 77 # exit all subshells
)
echo not here
)
echo not here either
set -E
in combination with ERR
traps is a bit like an improved version of set -e
in that it allows you to define your own error handling.
In zsh, ERR traps are inherited automatically, so you don't need set -E
, you can also define traps as TRAPERR()
functions, and modify them through $functions[TRAPERR]
, like functions[TRAPERR]="echo was here; $functions[TRAPERR]"
edited Aug 21 '15 at 14:31
answered Sep 18 '12 at 21:19
Stéphane Chazelas
298k54563910
298k54563910
1
Interesting solution! Clearly more elegant thankill $$
.
– user13742
Sep 19 '12 at 9:23
2
One thing to watch out for, this trap won't handle interpolated commands, e.g.echo "$(exit 77)"
; the script will carry on as if we'd writtenecho ""
– Warbo
Mar 30 '16 at 14:58
Interresting! Is there any luck on (quite older) bash that doesn't have -E ? maybe we have to resort to defining a trap on a USER signal and using a kill to that signal? I'll do some reasearch too...
– Olivier Dulac
Apr 6 '16 at 18:44
How to know, when not being in a sub-shell trap, in order to return 1 instead of 77?
– ceving
Nov 9 '16 at 14:38
add a comment |
1
Interesting solution! Clearly more elegant thankill $$
.
– user13742
Sep 19 '12 at 9:23
2
One thing to watch out for, this trap won't handle interpolated commands, e.g.echo "$(exit 77)"
; the script will carry on as if we'd writtenecho ""
– Warbo
Mar 30 '16 at 14:58
Interresting! Is there any luck on (quite older) bash that doesn't have -E ? maybe we have to resort to defining a trap on a USER signal and using a kill to that signal? I'll do some reasearch too...
– Olivier Dulac
Apr 6 '16 at 18:44
How to know, when not being in a sub-shell trap, in order to return 1 instead of 77?
– ceving
Nov 9 '16 at 14:38
1
1
Interesting solution! Clearly more elegant than
kill $$
.– user13742
Sep 19 '12 at 9:23
Interesting solution! Clearly more elegant than
kill $$
.– user13742
Sep 19 '12 at 9:23
2
2
One thing to watch out for, this trap won't handle interpolated commands, e.g.
echo "$(exit 77)"
; the script will carry on as if we'd written echo ""
– Warbo
Mar 30 '16 at 14:58
One thing to watch out for, this trap won't handle interpolated commands, e.g.
echo "$(exit 77)"
; the script will carry on as if we'd written echo ""
– Warbo
Mar 30 '16 at 14:58
Interresting! Is there any luck on (quite older) bash that doesn't have -E ? maybe we have to resort to defining a trap on a USER signal and using a kill to that signal? I'll do some reasearch too...
– Olivier Dulac
Apr 6 '16 at 18:44
Interresting! Is there any luck on (quite older) bash that doesn't have -E ? maybe we have to resort to defining a trap on a USER signal and using a kill to that signal? I'll do some reasearch too...
– Olivier Dulac
Apr 6 '16 at 18:44
How to know, when not being in a sub-shell trap, in order to return 1 instead of 77?
– ceving
Nov 9 '16 at 14:38
How to know, when not being in a sub-shell trap, in order to return 1 instead of 77?
– ceving
Nov 9 '16 at 14:38
add a comment |
As an alternative to kill $$
, you may also try kill 0
, it will work in the case of nested subshells (all callers and side process will receive the signal) … but it's still brutal and ugly.
2
Wouldn't this kill process id 0?
– Ernest A C
Sep 18 '12 at 18:35
4
That'll kill the entire process group. You may hit things you don't want (if for example you've started some things in the background).
– derobert
Sep 18 '12 at 19:11
2
@ErnestAC see the kill(2) manpage, pids ≤0 have special meaning.
– derobert
Sep 18 '12 at 19:15
add a comment |
As an alternative to kill $$
, you may also try kill 0
, it will work in the case of nested subshells (all callers and side process will receive the signal) … but it's still brutal and ugly.
2
Wouldn't this kill process id 0?
– Ernest A C
Sep 18 '12 at 18:35
4
That'll kill the entire process group. You may hit things you don't want (if for example you've started some things in the background).
– derobert
Sep 18 '12 at 19:11
2
@ErnestAC see the kill(2) manpage, pids ≤0 have special meaning.
– derobert
Sep 18 '12 at 19:15
add a comment |
As an alternative to kill $$
, you may also try kill 0
, it will work in the case of nested subshells (all callers and side process will receive the signal) … but it's still brutal and ugly.
As an alternative to kill $$
, you may also try kill 0
, it will work in the case of nested subshells (all callers and side process will receive the signal) … but it's still brutal and ugly.
answered Sep 18 '12 at 18:18
Stéphane Gimenez
19.2k15074
19.2k15074
2
Wouldn't this kill process id 0?
– Ernest A C
Sep 18 '12 at 18:35
4
That'll kill the entire process group. You may hit things you don't want (if for example you've started some things in the background).
– derobert
Sep 18 '12 at 19:11
2
@ErnestAC see the kill(2) manpage, pids ≤0 have special meaning.
– derobert
Sep 18 '12 at 19:15
add a comment |
2
Wouldn't this kill process id 0?
– Ernest A C
Sep 18 '12 at 18:35
4
That'll kill the entire process group. You may hit things you don't want (if for example you've started some things in the background).
– derobert
Sep 18 '12 at 19:11
2
@ErnestAC see the kill(2) manpage, pids ≤0 have special meaning.
– derobert
Sep 18 '12 at 19:15
2
2
Wouldn't this kill process id 0?
– Ernest A C
Sep 18 '12 at 18:35
Wouldn't this kill process id 0?
– Ernest A C
Sep 18 '12 at 18:35
4
4
That'll kill the entire process group. You may hit things you don't want (if for example you've started some things in the background).
– derobert
Sep 18 '12 at 19:11
That'll kill the entire process group. You may hit things you don't want (if for example you've started some things in the background).
– derobert
Sep 18 '12 at 19:11
2
2
@ErnestAC see the kill(2) manpage, pids ≤0 have special meaning.
– derobert
Sep 18 '12 at 19:15
@ErnestAC see the kill(2) manpage, pids ≤0 have special meaning.
– derobert
Sep 18 '12 at 19:15
add a comment |
Try this ...
stop ()
echo "$1" 1>&2
exit 1
func ()
if $1; then
echo "foo"
else
stop "something went wrong"
fi
echo "shell..."
func $1
echo "subshell..."
result=`func $1`
echo "shell..."
echo "result=$result"
The results I get are ...
# test_exitsubshell true
shell...
foo
subshell...
shell...
result=foo
# test_exitsubshell false
shell...
something went wrong
Notes
- Parameterized to allow the
if
test to betrue
orfalse
(see the 2 runs) - When the
if
test isfalse
, we never reach the subshell.
This is very similar to the original idea the user was posting about and said didn't work. I don't think this works for the subshell case. Your test using false exits after the "shell" case and never gets to the "subshell" test case. I believe it would fail for that case since the subshell would exit from the "exit 1" call but does not propagate the error to the outer shell.
– stuckj
Oct 12 '16 at 17:49
add a comment |
Try this ...
stop ()
echo "$1" 1>&2
exit 1
func ()
if $1; then
echo "foo"
else
stop "something went wrong"
fi
echo "shell..."
func $1
echo "subshell..."
result=`func $1`
echo "shell..."
echo "result=$result"
The results I get are ...
# test_exitsubshell true
shell...
foo
subshell...
shell...
result=foo
# test_exitsubshell false
shell...
something went wrong
Notes
- Parameterized to allow the
if
test to betrue
orfalse
(see the 2 runs) - When the
if
test isfalse
, we never reach the subshell.
This is very similar to the original idea the user was posting about and said didn't work. I don't think this works for the subshell case. Your test using false exits after the "shell" case and never gets to the "subshell" test case. I believe it would fail for that case since the subshell would exit from the "exit 1" call but does not propagate the error to the outer shell.
– stuckj
Oct 12 '16 at 17:49
add a comment |
Try this ...
stop ()
echo "$1" 1>&2
exit 1
func ()
if $1; then
echo "foo"
else
stop "something went wrong"
fi
echo "shell..."
func $1
echo "subshell..."
result=`func $1`
echo "shell..."
echo "result=$result"
The results I get are ...
# test_exitsubshell true
shell...
foo
subshell...
shell...
result=foo
# test_exitsubshell false
shell...
something went wrong
Notes
- Parameterized to allow the
if
test to betrue
orfalse
(see the 2 runs) - When the
if
test isfalse
, we never reach the subshell.
Try this ...
stop ()
echo "$1" 1>&2
exit 1
func ()
if $1; then
echo "foo"
else
stop "something went wrong"
fi
echo "shell..."
func $1
echo "subshell..."
result=`func $1`
echo "shell..."
echo "result=$result"
The results I get are ...
# test_exitsubshell true
shell...
foo
subshell...
shell...
result=foo
# test_exitsubshell false
shell...
something went wrong
Notes
- Parameterized to allow the
if
test to betrue
orfalse
(see the 2 runs) - When the
if
test isfalse
, we never reach the subshell.
answered Oct 2 '14 at 23:36
DocSalvager
1,31021732
1,31021732
This is very similar to the original idea the user was posting about and said didn't work. I don't think this works for the subshell case. Your test using false exits after the "shell" case and never gets to the "subshell" test case. I believe it would fail for that case since the subshell would exit from the "exit 1" call but does not propagate the error to the outer shell.
– stuckj
Oct 12 '16 at 17:49
add a comment |
This is very similar to the original idea the user was posting about and said didn't work. I don't think this works for the subshell case. Your test using false exits after the "shell" case and never gets to the "subshell" test case. I believe it would fail for that case since the subshell would exit from the "exit 1" call but does not propagate the error to the outer shell.
– stuckj
Oct 12 '16 at 17:49
This is very similar to the original idea the user was posting about and said didn't work. I don't think this works for the subshell case. Your test using false exits after the "shell" case and never gets to the "subshell" test case. I believe it would fail for that case since the subshell would exit from the "exit 1" call but does not propagate the error to the outer shell.
– stuckj
Oct 12 '16 at 17:49
This is very similar to the original idea the user was posting about and said didn't work. I don't think this works for the subshell case. Your test using false exits after the "shell" case and never gets to the "subshell" test case. I believe it would fail for that case since the subshell would exit from the "exit 1" call but does not propagate the error to the outer shell.
– stuckj
Oct 12 '16 at 17:49
add a comment |
(Bash specific answer)
Bash has no concept of exceptions.
However, with set -o errexit (or the equivalent: set -e) at the outermost level, the failed command will result in the subshell exiting with a non-zero exit status.
If this is a set of nested subshells without conditionals around the execution of those subshells, it will effectively 'roll up' the entire script and exit.
This can be tricky when trying to include bits of various bash code into a larger script. One chunk of bash may work just fine on its own, but when executed under errexit (or without errexit), behave in unexpected ways.
[192.168.13.16 (f0f5e19e) ~ 22:58:22]# bash -o errexit /tmp/foo
something went wrong
[192.168.13.16 (f0f5e19e) ~ 22:58:31]# bash /tmp/foo
something went wrong
But we got here anyways
[192.168.13.16 (f0f5e19e) ~ 22:58:37]# cat /tmp/foo
#!/bin/bash
stop ()
echo "$1"
exit 1
if false; then
echo "foo"
else
(
stop "something went wrong"
)
echo "But we got here anyways"
fi
[192.168.13.16 (f0f5e19e) ~ 22:58:40]#
add a comment |
(Bash specific answer)
Bash has no concept of exceptions.
However, with set -o errexit (or the equivalent: set -e) at the outermost level, the failed command will result in the subshell exiting with a non-zero exit status.
If this is a set of nested subshells without conditionals around the execution of those subshells, it will effectively 'roll up' the entire script and exit.
This can be tricky when trying to include bits of various bash code into a larger script. One chunk of bash may work just fine on its own, but when executed under errexit (or without errexit), behave in unexpected ways.
[192.168.13.16 (f0f5e19e) ~ 22:58:22]# bash -o errexit /tmp/foo
something went wrong
[192.168.13.16 (f0f5e19e) ~ 22:58:31]# bash /tmp/foo
something went wrong
But we got here anyways
[192.168.13.16 (f0f5e19e) ~ 22:58:37]# cat /tmp/foo
#!/bin/bash
stop ()
echo "$1"
exit 1
if false; then
echo "foo"
else
(
stop "something went wrong"
)
echo "But we got here anyways"
fi
[192.168.13.16 (f0f5e19e) ~ 22:58:40]#
add a comment |
(Bash specific answer)
Bash has no concept of exceptions.
However, with set -o errexit (or the equivalent: set -e) at the outermost level, the failed command will result in the subshell exiting with a non-zero exit status.
If this is a set of nested subshells without conditionals around the execution of those subshells, it will effectively 'roll up' the entire script and exit.
This can be tricky when trying to include bits of various bash code into a larger script. One chunk of bash may work just fine on its own, but when executed under errexit (or without errexit), behave in unexpected ways.
[192.168.13.16 (f0f5e19e) ~ 22:58:22]# bash -o errexit /tmp/foo
something went wrong
[192.168.13.16 (f0f5e19e) ~ 22:58:31]# bash /tmp/foo
something went wrong
But we got here anyways
[192.168.13.16 (f0f5e19e) ~ 22:58:37]# cat /tmp/foo
#!/bin/bash
stop ()
echo "$1"
exit 1
if false; then
echo "foo"
else
(
stop "something went wrong"
)
echo "But we got here anyways"
fi
[192.168.13.16 (f0f5e19e) ~ 22:58:40]#
(Bash specific answer)
Bash has no concept of exceptions.
However, with set -o errexit (or the equivalent: set -e) at the outermost level, the failed command will result in the subshell exiting with a non-zero exit status.
If this is a set of nested subshells without conditionals around the execution of those subshells, it will effectively 'roll up' the entire script and exit.
This can be tricky when trying to include bits of various bash code into a larger script. One chunk of bash may work just fine on its own, but when executed under errexit (or without errexit), behave in unexpected ways.
[192.168.13.16 (f0f5e19e) ~ 22:58:22]# bash -o errexit /tmp/foo
something went wrong
[192.168.13.16 (f0f5e19e) ~ 22:58:31]# bash /tmp/foo
something went wrong
But we got here anyways
[192.168.13.16 (f0f5e19e) ~ 22:58:37]# cat /tmp/foo
#!/bin/bash
stop ()
echo "$1"
exit 1
if false; then
echo "foo"
else
(
stop "something went wrong"
)
echo "But we got here anyways"
fi
[192.168.13.16 (f0f5e19e) ~ 22:58:40]#
edited Dec 10 at 23:01
answered Dec 10 at 22:54
Brian Chrisman
1163
1163
add a comment |
add a comment |
My example to exit in one liner:
COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit
add a comment |
My example to exit in one liner:
COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit
add a comment |
My example to exit in one liner:
COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit
My example to exit in one liner:
COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit
edited Jul 19 '17 at 9:41
Anthon
60.2k17102163
60.2k17102163
answered Jul 19 '17 at 9:04
vicente
1
1
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f48533%2fexit-shell-script-from-a-subshell%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
i want a function "stop" that prints a message to stderr and stops the script, but it doesn't stop when the function that calls stop is executed in a sub-shell, like in the example
– Ernest A C
Sep 18 '12 at 16:41
2
Of course, because it exits from the subshell not the current one. Simply call the function directly:
func
.– user13742
Sep 18 '12 at 16:42
1
i can't call it directly because it returns a string that has to be stored in a variable
– Ernest A C
Sep 18 '12 at 16:53
1
@ErnestAC Please provide all the details in the original question. The above function does not return a string.
– user13742
Sep 18 '12 at 17:03
1
@htor I changed the example
– Ernest A C
Sep 18 '12 at 17:29