How can I detect if I'm in a subshell?Do parentheses really put the command in a subshell?How can I get the pid of a subshell?exit shell script from a subshellcurly braces and subshellExpand subshell before executing it?Assign Subshell background process pid to variableHow to run subshell commands over SSH?set -e in a subshellgrabbing exit code of background process/subshellHow can I get the pid of a subshell?How can I stop a child process of a subshell (as per SIGSTOP) before the subshell exits?How to handle async subshell exit

Why is reverb typically called "wet' or "drippy"?

Why is Macron seemingly opposing an article 50 extension?

The DM is unapologetically providing TPK encounters; what can we do?

Black hole as a storage device?

Ubuntu 19.10: why is the "locate" command missing?

Degraded Array. RAID 6 with three disk failure

Encrypt folder on Linux that can only be decrypted on that specific OS and device

Is it crucial for a UX designer to understand the principles and concepts behind Object Oriented Programming?

Drawing hexagonal lattice in LaTex using Cartesian coordinates

How to print a list of possible matches from C-n?

How do we distinguish old craters from new ones on the Moon?

What is the most life you can have at the end of your first turn with only three cards?

How to make the number 49?

What is the history of the Eldritch Knight as a class/character option?

How to create numeronyms in bash

Extract partitions of images after edge detection

Why there are no major political movements worried about asteroid/comet impact?

How to write strategy and schemes beyond my real-life capabilities?

Why would the command "ls *" generate an error?

What element, if any, would justify mining stars (financially)?

If authors leave out diacritics, should I correct them or leave it as written?

Do you make me up?

How to express "naked" in different situations?

Famous easy to understand examples of a confounding variable invalidating a study



How can I detect if I'm in a subshell?


Do parentheses really put the command in a subshell?How can I get the pid of a subshell?exit shell script from a subshellcurly braces and subshellExpand subshell before executing it?Assign Subshell background process pid to variableHow to run subshell commands over SSH?set -e in a subshellgrabbing exit code of background process/subshellHow can I get the pid of a subshell?How can I stop a child process of a subshell (as per SIGSTOP) before the subshell exits?How to handle async subshell exit






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









24

















I'm trying to write a function to replace the functionality of the exit builtin to prevent myself from exiting the terminal.



I have attempted to use the SHLVL environment variable but it doesn't seem to change within subshells:



$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2


My function is as follows:



exit () 
if [[ $SHLVL -eq 1 ]]; then
printf '%sn' "Nice try!" >&2
else
command exit
fi




This won't allow me to use exit within subshells though:



$ exit
Nice try!
$ (exit)
Nice try!


What is a good method to detect whether or not I am in a subshell?










share|improve this question























  • 3





    stackoverflow.com/questions/4511407/…

    – K7AAY
    Jun 12 at 18:40






  • 1





    That is because of this. $SHLVL is 1 because you are still in shell level 1 even though the echo $SHLVL command is run in a "subshell". According to that post, subshells spawned with parenthesis (...) inherit all the properties of the parent process. The answers provided are more robust solutions to determining your shell level.

    – kemotep
    Jun 12 at 18:52







  • 1





    Possible duplicate of How can I get the pid of a subshell?

    – mosvy
    Jun 13 at 5:45






  • 5





    @mosvy I feel like that is a different question. e.g. the BASH_SUBSHELL answer (even if controversial) wouldn't apply to that question.

    – Sparhawk
    Jun 13 at 9:39






  • 2





    Saw the title on HNQ and thought this was a quantum mechanics question...

    – Mehrdad
    Jun 13 at 22:47

















24

















I'm trying to write a function to replace the functionality of the exit builtin to prevent myself from exiting the terminal.



I have attempted to use the SHLVL environment variable but it doesn't seem to change within subshells:



$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2


My function is as follows:



exit () 
if [[ $SHLVL -eq 1 ]]; then
printf '%sn' "Nice try!" >&2
else
command exit
fi




This won't allow me to use exit within subshells though:



$ exit
Nice try!
$ (exit)
Nice try!


What is a good method to detect whether or not I am in a subshell?










share|improve this question























  • 3





    stackoverflow.com/questions/4511407/…

    – K7AAY
    Jun 12 at 18:40






  • 1





    That is because of this. $SHLVL is 1 because you are still in shell level 1 even though the echo $SHLVL command is run in a "subshell". According to that post, subshells spawned with parenthesis (...) inherit all the properties of the parent process. The answers provided are more robust solutions to determining your shell level.

    – kemotep
    Jun 12 at 18:52







  • 1





    Possible duplicate of How can I get the pid of a subshell?

    – mosvy
    Jun 13 at 5:45






  • 5





    @mosvy I feel like that is a different question. e.g. the BASH_SUBSHELL answer (even if controversial) wouldn't apply to that question.

    – Sparhawk
    Jun 13 at 9:39






  • 2





    Saw the title on HNQ and thought this was a quantum mechanics question...

    – Mehrdad
    Jun 13 at 22:47













24












24








24


3






I'm trying to write a function to replace the functionality of the exit builtin to prevent myself from exiting the terminal.



I have attempted to use the SHLVL environment variable but it doesn't seem to change within subshells:



$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2


My function is as follows:



exit () 
if [[ $SHLVL -eq 1 ]]; then
printf '%sn' "Nice try!" >&2
else
command exit
fi




This won't allow me to use exit within subshells though:



$ exit
Nice try!
$ (exit)
Nice try!


What is a good method to detect whether or not I am in a subshell?










share|improve this question

















I'm trying to write a function to replace the functionality of the exit builtin to prevent myself from exiting the terminal.



I have attempted to use the SHLVL environment variable but it doesn't seem to change within subshells:



$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2


My function is as follows:



exit () 
if [[ $SHLVL -eq 1 ]]; then
printf '%sn' "Nice try!" >&2
else
command exit
fi




This won't allow me to use exit within subshells though:



$ exit
Nice try!
$ (exit)
Nice try!


What is a good method to detect whether or not I am in a subshell?







bash shell exit subshell






share|improve this question
















share|improve this question













share|improve this question




share|improve this question








edited Jun 16 at 10:15









Jeff Schaller

50.9k11 gold badges75 silver badges170 bronze badges




50.9k11 gold badges75 silver badges170 bronze badges










asked Jun 12 at 18:35









Jesse_bJesse_b

19.8k3 gold badges47 silver badges90 bronze badges




19.8k3 gold badges47 silver badges90 bronze badges










  • 3





    stackoverflow.com/questions/4511407/…

    – K7AAY
    Jun 12 at 18:40






  • 1





    That is because of this. $SHLVL is 1 because you are still in shell level 1 even though the echo $SHLVL command is run in a "subshell". According to that post, subshells spawned with parenthesis (...) inherit all the properties of the parent process. The answers provided are more robust solutions to determining your shell level.

    – kemotep
    Jun 12 at 18:52







  • 1





    Possible duplicate of How can I get the pid of a subshell?

    – mosvy
    Jun 13 at 5:45






  • 5





    @mosvy I feel like that is a different question. e.g. the BASH_SUBSHELL answer (even if controversial) wouldn't apply to that question.

    – Sparhawk
    Jun 13 at 9:39






  • 2





    Saw the title on HNQ and thought this was a quantum mechanics question...

    – Mehrdad
    Jun 13 at 22:47












  • 3





    stackoverflow.com/questions/4511407/…

    – K7AAY
    Jun 12 at 18:40






  • 1





    That is because of this. $SHLVL is 1 because you are still in shell level 1 even though the echo $SHLVL command is run in a "subshell". According to that post, subshells spawned with parenthesis (...) inherit all the properties of the parent process. The answers provided are more robust solutions to determining your shell level.

    – kemotep
    Jun 12 at 18:52







  • 1





    Possible duplicate of How can I get the pid of a subshell?

    – mosvy
    Jun 13 at 5:45






  • 5





    @mosvy I feel like that is a different question. e.g. the BASH_SUBSHELL answer (even if controversial) wouldn't apply to that question.

    – Sparhawk
    Jun 13 at 9:39






  • 2





    Saw the title on HNQ and thought this was a quantum mechanics question...

    – Mehrdad
    Jun 13 at 22:47







3




3





stackoverflow.com/questions/4511407/…

– K7AAY
Jun 12 at 18:40





stackoverflow.com/questions/4511407/…

– K7AAY
Jun 12 at 18:40




1




1





That is because of this. $SHLVL is 1 because you are still in shell level 1 even though the echo $SHLVL command is run in a "subshell". According to that post, subshells spawned with parenthesis (...) inherit all the properties of the parent process. The answers provided are more robust solutions to determining your shell level.

– kemotep
Jun 12 at 18:52






That is because of this. $SHLVL is 1 because you are still in shell level 1 even though the echo $SHLVL command is run in a "subshell". According to that post, subshells spawned with parenthesis (...) inherit all the properties of the parent process. The answers provided are more robust solutions to determining your shell level.

– kemotep
Jun 12 at 18:52





1




1





Possible duplicate of How can I get the pid of a subshell?

– mosvy
Jun 13 at 5:45





Possible duplicate of How can I get the pid of a subshell?

– mosvy
Jun 13 at 5:45




5




5





@mosvy I feel like that is a different question. e.g. the BASH_SUBSHELL answer (even if controversial) wouldn't apply to that question.

– Sparhawk
Jun 13 at 9:39





@mosvy I feel like that is a different question. e.g. the BASH_SUBSHELL answer (even if controversial) wouldn't apply to that question.

– Sparhawk
Jun 13 at 9:39




2




2





Saw the title on HNQ and thought this was a quantum mechanics question...

– Mehrdad
Jun 13 at 22:47





Saw the title on HNQ and thought this was a quantum mechanics question...

– Mehrdad
Jun 13 at 22:47










3 Answers
3






active

oldest

votes


















43


















In bash, you can compare $BASHPID to $$



$ ( if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi )
subshell
$ if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi
not subshell


If you're not in bash, $$ should remain the same in a subshell, so you'd need some other way of getting your actual process ID.



One way to get your actual pid is sh -c 'echo $PPID'. If you just put that in a plain ( … ) it may appear not to work, as your shell has optimized away the fork. Try extra no-op commands ( : ; sh -c 'echo $PPID'; : ) to make it think the subshell is too complicated to optimize away. Credit goes to John1024 on Stack Overflow for that approach.






share|improve this answer




























  • You might want to change that to (sh -c 'echo $PPID'; : ) — see my comment on John1024’s answer.

    – G-Man
    Jun 19 at 21:15











  • @G-Man Well, that was just to test it (since in actual use it'd be in something way more complicated)... but yeah, would be best if the test worked in all shells. So I've put a no-op both before and after, that will hopefully handle everything.

    – derobert
    Jun 19 at 21:45


















38


















How about BASH_SUBSHELL?




BASH_SUBSHELL

      Incremented by one within each subshell or subshell environment when the shell

      begins executing in that environment. The initial value is 0.




$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1





share|improve this answer





















  • 15





    It would have been a convenient command in the movie Inception.

    – Eric Duminil
    Jun 13 at 18:56











  • In Inception it's probably $SHLVL

    – Granny Aching
    Jun 14 at 17:14


















19


















[this should've been a comment, but my comments tend to be deleted by moderators, so this will stay as an answer that I could use it as a reference even if deleted]



Using BASH_SUBSHELL is completely unreliable as it be only set to 1 in some subshells, not in all subshells.



$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0


Before claiming that the subprocess a pipeline command is run in is not a really real subshell, consider this man bash snippet:




Each command in a pipeline is executed as a separate process (i.e., in a subshell).




and the practical implications -- it's whether a script fragment is run a subprocess or not which is essential, not some terminology quibble.



The only solution, as already explained in the answers to this question is to check whether $BASHPID equals $$ or, portably but much less efficient:



if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
echo you're in a subshell
fi





share|improve this answer























  • 11





    Nit: BASH_SUBSHELL is set pretty reliably, but getting its value correctly is iffy. Note what the docs say: "Incremented by one within each subshell or subshell environment when the shell begins executing in that environment." I think that in the pipe example, bash hasn't yet begun executing in that subshell when the variable is expanded. You can compare echo $BASH_VERSION with declare -p BASH_VERSION - the latter should reliably output 1 with pipes, background jobs, etc.

    – muru
    Jun 13 at 1:20






  • 6





    Even say, eval 'echo $BASH_SUBSHELL $BASHPID' | cat will output 1 for BASH_SUBSHELL, because the variable is expanded after execution has started.

    – muru
    Jun 13 at 6:02






  • 4





    all those arguments should also apply to to process & commands substitution, bg processes, yet it's only the pipelines which are different. Looking at the code, incrementing subshell_level really is deferred in the case of foreground pipelines, which probably has some reason, but which I'm not able to make out ;-)

    – mosvy
    Jun 13 at 6:18







  • 2





    You're right. Seems Chet explicitly intends it that way. lists.gnu.org/archive/html/bug-bash/2015-06/msg00050.html : "BASH_SUBSHELL measures (...) subshells, not pipeline elements." lists.gnu.org/archive/html/bug-bash/2015-06/msg00054.html: "I'm going to think about whether I should document the status quo or expand the definition of `subshell' that $BASH_SUBSHELL reflects."

    – muru
    Jun 13 at 7:11






  • 2





    @JoL you're wrong, the expansion happens in the separate process too, please read the links and examples from this discussion above; or just try with echo $$ $BASHPID $BASH_SUBSHELL | cat.

    – mosvy
    Jun 13 at 19:45













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/4.0/"u003ecc by-sa 4.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%2f524506%2fhow-can-i-detect-if-im-in-a-subshell%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown


























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









43


















In bash, you can compare $BASHPID to $$



$ ( if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi )
subshell
$ if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi
not subshell


If you're not in bash, $$ should remain the same in a subshell, so you'd need some other way of getting your actual process ID.



One way to get your actual pid is sh -c 'echo $PPID'. If you just put that in a plain ( … ) it may appear not to work, as your shell has optimized away the fork. Try extra no-op commands ( : ; sh -c 'echo $PPID'; : ) to make it think the subshell is too complicated to optimize away. Credit goes to John1024 on Stack Overflow for that approach.






share|improve this answer




























  • You might want to change that to (sh -c 'echo $PPID'; : ) — see my comment on John1024’s answer.

    – G-Man
    Jun 19 at 21:15











  • @G-Man Well, that was just to test it (since in actual use it'd be in something way more complicated)... but yeah, would be best if the test worked in all shells. So I've put a no-op both before and after, that will hopefully handle everything.

    – derobert
    Jun 19 at 21:45















43


















In bash, you can compare $BASHPID to $$



$ ( if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi )
subshell
$ if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi
not subshell


If you're not in bash, $$ should remain the same in a subshell, so you'd need some other way of getting your actual process ID.



One way to get your actual pid is sh -c 'echo $PPID'. If you just put that in a plain ( … ) it may appear not to work, as your shell has optimized away the fork. Try extra no-op commands ( : ; sh -c 'echo $PPID'; : ) to make it think the subshell is too complicated to optimize away. Credit goes to John1024 on Stack Overflow for that approach.






share|improve this answer




























  • You might want to change that to (sh -c 'echo $PPID'; : ) — see my comment on John1024’s answer.

    – G-Man
    Jun 19 at 21:15











  • @G-Man Well, that was just to test it (since in actual use it'd be in something way more complicated)... but yeah, would be best if the test worked in all shells. So I've put a no-op both before and after, that will hopefully handle everything.

    – derobert
    Jun 19 at 21:45













43














43










43









In bash, you can compare $BASHPID to $$



$ ( if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi )
subshell
$ if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi
not subshell


If you're not in bash, $$ should remain the same in a subshell, so you'd need some other way of getting your actual process ID.



One way to get your actual pid is sh -c 'echo $PPID'. If you just put that in a plain ( … ) it may appear not to work, as your shell has optimized away the fork. Try extra no-op commands ( : ; sh -c 'echo $PPID'; : ) to make it think the subshell is too complicated to optimize away. Credit goes to John1024 on Stack Overflow for that approach.






share|improve this answer
















In bash, you can compare $BASHPID to $$



$ ( if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi )
subshell
$ if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi
not subshell


If you're not in bash, $$ should remain the same in a subshell, so you'd need some other way of getting your actual process ID.



One way to get your actual pid is sh -c 'echo $PPID'. If you just put that in a plain ( … ) it may appear not to work, as your shell has optimized away the fork. Try extra no-op commands ( : ; sh -c 'echo $PPID'; : ) to make it think the subshell is too complicated to optimize away. Credit goes to John1024 on Stack Overflow for that approach.







share|improve this answer















share|improve this answer




share|improve this answer








edited Jun 19 at 21:43

























answered Jun 12 at 18:46









derobertderobert

81.2k9 gold badges183 silver badges237 bronze badges




81.2k9 gold badges183 silver badges237 bronze badges















  • You might want to change that to (sh -c 'echo $PPID'; : ) — see my comment on John1024’s answer.

    – G-Man
    Jun 19 at 21:15











  • @G-Man Well, that was just to test it (since in actual use it'd be in something way more complicated)... but yeah, would be best if the test worked in all shells. So I've put a no-op both before and after, that will hopefully handle everything.

    – derobert
    Jun 19 at 21:45

















  • You might want to change that to (sh -c 'echo $PPID'; : ) — see my comment on John1024’s answer.

    – G-Man
    Jun 19 at 21:15











  • @G-Man Well, that was just to test it (since in actual use it'd be in something way more complicated)... but yeah, would be best if the test worked in all shells. So I've put a no-op both before and after, that will hopefully handle everything.

    – derobert
    Jun 19 at 21:45
















You might want to change that to (sh -c 'echo $PPID'; : ) — see my comment on John1024’s answer.

– G-Man
Jun 19 at 21:15





You might want to change that to (sh -c 'echo $PPID'; : ) — see my comment on John1024’s answer.

– G-Man
Jun 19 at 21:15













@G-Man Well, that was just to test it (since in actual use it'd be in something way more complicated)... but yeah, would be best if the test worked in all shells. So I've put a no-op both before and after, that will hopefully handle everything.

– derobert
Jun 19 at 21:45





@G-Man Well, that was just to test it (since in actual use it'd be in something way more complicated)... but yeah, would be best if the test worked in all shells. So I've put a no-op both before and after, that will hopefully handle everything.

– derobert
Jun 19 at 21:45













38


















How about BASH_SUBSHELL?




BASH_SUBSHELL

      Incremented by one within each subshell or subshell environment when the shell

      begins executing in that environment. The initial value is 0.




$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1





share|improve this answer





















  • 15





    It would have been a convenient command in the movie Inception.

    – Eric Duminil
    Jun 13 at 18:56











  • In Inception it's probably $SHLVL

    – Granny Aching
    Jun 14 at 17:14















38


















How about BASH_SUBSHELL?




BASH_SUBSHELL

      Incremented by one within each subshell or subshell environment when the shell

      begins executing in that environment. The initial value is 0.




$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1





share|improve this answer





















  • 15





    It would have been a convenient command in the movie Inception.

    – Eric Duminil
    Jun 13 at 18:56











  • In Inception it's probably $SHLVL

    – Granny Aching
    Jun 14 at 17:14













38














38










38









How about BASH_SUBSHELL?




BASH_SUBSHELL

      Incremented by one within each subshell or subshell environment when the shell

      begins executing in that environment. The initial value is 0.




$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1





share|improve this answer














How about BASH_SUBSHELL?




BASH_SUBSHELL

      Incremented by one within each subshell or subshell environment when the shell

      begins executing in that environment. The initial value is 0.




$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1






share|improve this answer













share|improve this answer




share|improve this answer










answered Jun 12 at 18:45









FreddyFreddy

9,7551 gold badge7 silver badges35 bronze badges




9,7551 gold badge7 silver badges35 bronze badges










  • 15





    It would have been a convenient command in the movie Inception.

    – Eric Duminil
    Jun 13 at 18:56











  • In Inception it's probably $SHLVL

    – Granny Aching
    Jun 14 at 17:14












  • 15





    It would have been a convenient command in the movie Inception.

    – Eric Duminil
    Jun 13 at 18:56











  • In Inception it's probably $SHLVL

    – Granny Aching
    Jun 14 at 17:14







15




15





It would have been a convenient command in the movie Inception.

– Eric Duminil
Jun 13 at 18:56





It would have been a convenient command in the movie Inception.

– Eric Duminil
Jun 13 at 18:56













In Inception it's probably $SHLVL

– Granny Aching
Jun 14 at 17:14





In Inception it's probably $SHLVL

– Granny Aching
Jun 14 at 17:14











19


















[this should've been a comment, but my comments tend to be deleted by moderators, so this will stay as an answer that I could use it as a reference even if deleted]



Using BASH_SUBSHELL is completely unreliable as it be only set to 1 in some subshells, not in all subshells.



$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0


Before claiming that the subprocess a pipeline command is run in is not a really real subshell, consider this man bash snippet:




Each command in a pipeline is executed as a separate process (i.e., in a subshell).




and the practical implications -- it's whether a script fragment is run a subprocess or not which is essential, not some terminology quibble.



The only solution, as already explained in the answers to this question is to check whether $BASHPID equals $$ or, portably but much less efficient:



if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
echo you're in a subshell
fi





share|improve this answer























  • 11





    Nit: BASH_SUBSHELL is set pretty reliably, but getting its value correctly is iffy. Note what the docs say: "Incremented by one within each subshell or subshell environment when the shell begins executing in that environment." I think that in the pipe example, bash hasn't yet begun executing in that subshell when the variable is expanded. You can compare echo $BASH_VERSION with declare -p BASH_VERSION - the latter should reliably output 1 with pipes, background jobs, etc.

    – muru
    Jun 13 at 1:20






  • 6





    Even say, eval 'echo $BASH_SUBSHELL $BASHPID' | cat will output 1 for BASH_SUBSHELL, because the variable is expanded after execution has started.

    – muru
    Jun 13 at 6:02






  • 4





    all those arguments should also apply to to process & commands substitution, bg processes, yet it's only the pipelines which are different. Looking at the code, incrementing subshell_level really is deferred in the case of foreground pipelines, which probably has some reason, but which I'm not able to make out ;-)

    – mosvy
    Jun 13 at 6:18







  • 2





    You're right. Seems Chet explicitly intends it that way. lists.gnu.org/archive/html/bug-bash/2015-06/msg00050.html : "BASH_SUBSHELL measures (...) subshells, not pipeline elements." lists.gnu.org/archive/html/bug-bash/2015-06/msg00054.html: "I'm going to think about whether I should document the status quo or expand the definition of `subshell' that $BASH_SUBSHELL reflects."

    – muru
    Jun 13 at 7:11






  • 2





    @JoL you're wrong, the expansion happens in the separate process too, please read the links and examples from this discussion above; or just try with echo $$ $BASHPID $BASH_SUBSHELL | cat.

    – mosvy
    Jun 13 at 19:45
















19


















[this should've been a comment, but my comments tend to be deleted by moderators, so this will stay as an answer that I could use it as a reference even if deleted]



Using BASH_SUBSHELL is completely unreliable as it be only set to 1 in some subshells, not in all subshells.



$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0


Before claiming that the subprocess a pipeline command is run in is not a really real subshell, consider this man bash snippet:




Each command in a pipeline is executed as a separate process (i.e., in a subshell).




and the practical implications -- it's whether a script fragment is run a subprocess or not which is essential, not some terminology quibble.



The only solution, as already explained in the answers to this question is to check whether $BASHPID equals $$ or, portably but much less efficient:



if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
echo you're in a subshell
fi





share|improve this answer























  • 11





    Nit: BASH_SUBSHELL is set pretty reliably, but getting its value correctly is iffy. Note what the docs say: "Incremented by one within each subshell or subshell environment when the shell begins executing in that environment." I think that in the pipe example, bash hasn't yet begun executing in that subshell when the variable is expanded. You can compare echo $BASH_VERSION with declare -p BASH_VERSION - the latter should reliably output 1 with pipes, background jobs, etc.

    – muru
    Jun 13 at 1:20






  • 6





    Even say, eval 'echo $BASH_SUBSHELL $BASHPID' | cat will output 1 for BASH_SUBSHELL, because the variable is expanded after execution has started.

    – muru
    Jun 13 at 6:02






  • 4





    all those arguments should also apply to to process & commands substitution, bg processes, yet it's only the pipelines which are different. Looking at the code, incrementing subshell_level really is deferred in the case of foreground pipelines, which probably has some reason, but which I'm not able to make out ;-)

    – mosvy
    Jun 13 at 6:18







  • 2





    You're right. Seems Chet explicitly intends it that way. lists.gnu.org/archive/html/bug-bash/2015-06/msg00050.html : "BASH_SUBSHELL measures (...) subshells, not pipeline elements." lists.gnu.org/archive/html/bug-bash/2015-06/msg00054.html: "I'm going to think about whether I should document the status quo or expand the definition of `subshell' that $BASH_SUBSHELL reflects."

    – muru
    Jun 13 at 7:11






  • 2





    @JoL you're wrong, the expansion happens in the separate process too, please read the links and examples from this discussion above; or just try with echo $$ $BASHPID $BASH_SUBSHELL | cat.

    – mosvy
    Jun 13 at 19:45














19














19










19









[this should've been a comment, but my comments tend to be deleted by moderators, so this will stay as an answer that I could use it as a reference even if deleted]



Using BASH_SUBSHELL is completely unreliable as it be only set to 1 in some subshells, not in all subshells.



$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0


Before claiming that the subprocess a pipeline command is run in is not a really real subshell, consider this man bash snippet:




Each command in a pipeline is executed as a separate process (i.e., in a subshell).




and the practical implications -- it's whether a script fragment is run a subprocess or not which is essential, not some terminology quibble.



The only solution, as already explained in the answers to this question is to check whether $BASHPID equals $$ or, portably but much less efficient:



if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
echo you're in a subshell
fi





share|improve this answer
















[this should've been a comment, but my comments tend to be deleted by moderators, so this will stay as an answer that I could use it as a reference even if deleted]



Using BASH_SUBSHELL is completely unreliable as it be only set to 1 in some subshells, not in all subshells.



$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0


Before claiming that the subprocess a pipeline command is run in is not a really real subshell, consider this man bash snippet:




Each command in a pipeline is executed as a separate process (i.e., in a subshell).




and the practical implications -- it's whether a script fragment is run a subprocess or not which is essential, not some terminology quibble.



The only solution, as already explained in the answers to this question is to check whether $BASHPID equals $$ or, portably but much less efficient:



if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
echo you're in a subshell
fi






share|improve this answer















share|improve this answer




share|improve this answer








edited Jun 13 at 0:06

























answered Jun 13 at 0:01









mosvymosvy

18.1k2 gold badges24 silver badges56 bronze badges




18.1k2 gold badges24 silver badges56 bronze badges










  • 11





    Nit: BASH_SUBSHELL is set pretty reliably, but getting its value correctly is iffy. Note what the docs say: "Incremented by one within each subshell or subshell environment when the shell begins executing in that environment." I think that in the pipe example, bash hasn't yet begun executing in that subshell when the variable is expanded. You can compare echo $BASH_VERSION with declare -p BASH_VERSION - the latter should reliably output 1 with pipes, background jobs, etc.

    – muru
    Jun 13 at 1:20






  • 6





    Even say, eval 'echo $BASH_SUBSHELL $BASHPID' | cat will output 1 for BASH_SUBSHELL, because the variable is expanded after execution has started.

    – muru
    Jun 13 at 6:02






  • 4





    all those arguments should also apply to to process & commands substitution, bg processes, yet it's only the pipelines which are different. Looking at the code, incrementing subshell_level really is deferred in the case of foreground pipelines, which probably has some reason, but which I'm not able to make out ;-)

    – mosvy
    Jun 13 at 6:18







  • 2





    You're right. Seems Chet explicitly intends it that way. lists.gnu.org/archive/html/bug-bash/2015-06/msg00050.html : "BASH_SUBSHELL measures (...) subshells, not pipeline elements." lists.gnu.org/archive/html/bug-bash/2015-06/msg00054.html: "I'm going to think about whether I should document the status quo or expand the definition of `subshell' that $BASH_SUBSHELL reflects."

    – muru
    Jun 13 at 7:11






  • 2





    @JoL you're wrong, the expansion happens in the separate process too, please read the links and examples from this discussion above; or just try with echo $$ $BASHPID $BASH_SUBSHELL | cat.

    – mosvy
    Jun 13 at 19:45













  • 11





    Nit: BASH_SUBSHELL is set pretty reliably, but getting its value correctly is iffy. Note what the docs say: "Incremented by one within each subshell or subshell environment when the shell begins executing in that environment." I think that in the pipe example, bash hasn't yet begun executing in that subshell when the variable is expanded. You can compare echo $BASH_VERSION with declare -p BASH_VERSION - the latter should reliably output 1 with pipes, background jobs, etc.

    – muru
    Jun 13 at 1:20






  • 6





    Even say, eval 'echo $BASH_SUBSHELL $BASHPID' | cat will output 1 for BASH_SUBSHELL, because the variable is expanded after execution has started.

    – muru
    Jun 13 at 6:02






  • 4





    all those arguments should also apply to to process & commands substitution, bg processes, yet it's only the pipelines which are different. Looking at the code, incrementing subshell_level really is deferred in the case of foreground pipelines, which probably has some reason, but which I'm not able to make out ;-)

    – mosvy
    Jun 13 at 6:18







  • 2





    You're right. Seems Chet explicitly intends it that way. lists.gnu.org/archive/html/bug-bash/2015-06/msg00050.html : "BASH_SUBSHELL measures (...) subshells, not pipeline elements." lists.gnu.org/archive/html/bug-bash/2015-06/msg00054.html: "I'm going to think about whether I should document the status quo or expand the definition of `subshell' that $BASH_SUBSHELL reflects."

    – muru
    Jun 13 at 7:11






  • 2





    @JoL you're wrong, the expansion happens in the separate process too, please read the links and examples from this discussion above; or just try with echo $$ $BASHPID $BASH_SUBSHELL | cat.

    – mosvy
    Jun 13 at 19:45








11




11





Nit: BASH_SUBSHELL is set pretty reliably, but getting its value correctly is iffy. Note what the docs say: "Incremented by one within each subshell or subshell environment when the shell begins executing in that environment." I think that in the pipe example, bash hasn't yet begun executing in that subshell when the variable is expanded. You can compare echo $BASH_VERSION with declare -p BASH_VERSION - the latter should reliably output 1 with pipes, background jobs, etc.

– muru
Jun 13 at 1:20





Nit: BASH_SUBSHELL is set pretty reliably, but getting its value correctly is iffy. Note what the docs say: "Incremented by one within each subshell or subshell environment when the shell begins executing in that environment." I think that in the pipe example, bash hasn't yet begun executing in that subshell when the variable is expanded. You can compare echo $BASH_VERSION with declare -p BASH_VERSION - the latter should reliably output 1 with pipes, background jobs, etc.

– muru
Jun 13 at 1:20




6




6





Even say, eval 'echo $BASH_SUBSHELL $BASHPID' | cat will output 1 for BASH_SUBSHELL, because the variable is expanded after execution has started.

– muru
Jun 13 at 6:02





Even say, eval 'echo $BASH_SUBSHELL $BASHPID' | cat will output 1 for BASH_SUBSHELL, because the variable is expanded after execution has started.

– muru
Jun 13 at 6:02




4




4





all those arguments should also apply to to process & commands substitution, bg processes, yet it's only the pipelines which are different. Looking at the code, incrementing subshell_level really is deferred in the case of foreground pipelines, which probably has some reason, but which I'm not able to make out ;-)

– mosvy
Jun 13 at 6:18






all those arguments should also apply to to process & commands substitution, bg processes, yet it's only the pipelines which are different. Looking at the code, incrementing subshell_level really is deferred in the case of foreground pipelines, which probably has some reason, but which I'm not able to make out ;-)

– mosvy
Jun 13 at 6:18





2




2





You're right. Seems Chet explicitly intends it that way. lists.gnu.org/archive/html/bug-bash/2015-06/msg00050.html : "BASH_SUBSHELL measures (...) subshells, not pipeline elements." lists.gnu.org/archive/html/bug-bash/2015-06/msg00054.html: "I'm going to think about whether I should document the status quo or expand the definition of `subshell' that $BASH_SUBSHELL reflects."

– muru
Jun 13 at 7:11





You're right. Seems Chet explicitly intends it that way. lists.gnu.org/archive/html/bug-bash/2015-06/msg00050.html : "BASH_SUBSHELL measures (...) subshells, not pipeline elements." lists.gnu.org/archive/html/bug-bash/2015-06/msg00054.html: "I'm going to think about whether I should document the status quo or expand the definition of `subshell' that $BASH_SUBSHELL reflects."

– muru
Jun 13 at 7:11




2




2





@JoL you're wrong, the expansion happens in the separate process too, please read the links and examples from this discussion above; or just try with echo $$ $BASHPID $BASH_SUBSHELL | cat.

– mosvy
Jun 13 at 19:45






@JoL you're wrong, the expansion happens in the separate process too, please read the links and examples from this discussion above; or just try with echo $$ $BASHPID $BASH_SUBSHELL | cat.

– mosvy
Jun 13 at 19:45



















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.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f524506%2fhow-can-i-detect-if-im-in-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

Tamil (spriik) Luke uk diar | Nawigatjuun

Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

Where does the image of a data connector as a sharp metal spike originate from?Where does the concept of infected people turning into zombies only after death originate from?Where does the motif of a reanimated human head originate?Where did the notion that Dragons could speak originate?Where does the archetypal image of the 'Grey' alien come from?Where did the suffix '-Man' originate?Where does the notion of being injured or killed by an illusion originate?Where did the term “sophont” originate?Where does the trope of magic spells being driven by advanced technology originate from?Where did the term “the living impaired” originate?