exit shell script from a subshell

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












26














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?










share|improve this question



















  • 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















26














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?










share|improve this question



















  • 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













26












26








26


10





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?










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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












  • 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










6 Answers
6






active

oldest

votes


















9














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.






share|improve this answer
















  • 4




    Thanks. I'd rather switch to Python, though.
    – Ernest A C
    Sep 18 '12 at 18:35


















32














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]"






share|improve this answer


















  • 1




    Interesting solution! Clearly more elegant than kill $$.
    – 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 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











  • 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


















6














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.






share|improve this answer
















  • 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


















0














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 be true or false (see the 2 runs)

  • When the if test is false, we never reach the subshell.





share|improve this answer




















  • 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


















0














(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]#





share|improve this answer






























    -2














    My example to exit in one liner:



    COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit





    share|improve this answer






















      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
      );



      );













      draft saved

      draft discarded


















      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









      9














      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.






      share|improve this answer
















      • 4




        Thanks. I'd rather switch to Python, though.
        – Ernest A C
        Sep 18 '12 at 18:35















      9














      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.






      share|improve this answer
















      • 4




        Thanks. I'd rather switch to Python, though.
        – Ernest A C
        Sep 18 '12 at 18:35













      9












      9








      9






      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.






      share|improve this answer












      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.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      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












      • 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













      32














      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]"






      share|improve this answer


















      • 1




        Interesting solution! Clearly more elegant than kill $$.
        – 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 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











      • 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















      32














      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]"






      share|improve this answer


















      • 1




        Interesting solution! Clearly more elegant than kill $$.
        – 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 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











      • 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













      32












      32








      32






      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]"






      share|improve this answer














      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]"







      share|improve this answer














      share|improve this answer



      share|improve this answer








      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 than kill $$.
        – 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 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











      • 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




        Interesting solution! Clearly more elegant than kill $$.
        – 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 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











      • 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











      6














      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.






      share|improve this answer
















      • 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















      6














      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.






      share|improve this answer
















      • 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













      6












      6








      6






      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.






      share|improve this answer












      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.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      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












      • 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











      0














      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 be true or false (see the 2 runs)

      • When the if test is false, we never reach the subshell.





      share|improve this answer




















      • 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















      0














      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 be true or false (see the 2 runs)

      • When the if test is false, we never reach the subshell.





      share|improve this answer




















      • 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













      0












      0








      0






      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 be true or false (see the 2 runs)

      • When the if test is false, we never reach the subshell.





      share|improve this answer












      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 be true or false (see the 2 runs)

      • When the if test is false, we never reach the subshell.






      share|improve this answer












      share|improve this answer



      share|improve this answer










      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
















      • 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











      0














      (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]#





      share|improve this answer



























        0














        (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]#





        share|improve this answer

























          0












          0








          0






          (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]#





          share|improve this answer














          (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]#






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Dec 10 at 23:01

























          answered Dec 10 at 22:54









          Brian Chrisman

          1163




          1163





















              -2














              My example to exit in one liner:



              COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit





              share|improve this answer



























                -2














                My example to exit in one liner:



                COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit





                share|improve this answer

























                  -2












                  -2








                  -2






                  My example to exit in one liner:



                  COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit





                  share|improve this answer














                  My example to exit in one liner:



                  COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Jul 19 '17 at 9:41









                  Anthon

                  60.2k17102163




                  60.2k17102163










                  answered Jul 19 '17 at 9:04









                  vicente

                  1




                  1



























                      draft saved

                      draft discarded
















































                      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.




                      draft saved


                      draft discarded














                      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





















































                      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






                      Popular posts from this blog

                      How to check contact read email or not when send email to Individual?

                      Bahrain

                      Postfix configuration issue with fips on centos 7; mailgun relay