38

In Advanced Bash-Scripting Guide, in example 27-4, 7-th line from the bottom, I've read this:

A function runs as a sub-process.

I did a test in Bash, and it seems that the above statement is wrong.

Searches on this site, Bash Man, and my search engine don't bring any light.

Do you have the answer and would like to explain?

  • 13
    As noted, that guide is misleading in the extreme. I recommend the Wooledge Bash Guide instead. – Wildcard Aug 24 '16 at 01:39
  • 1
    An important fact is that "Bash" avoids to create subshells. They are expensive, has your own environment, and those affect performance of the script as well the way how the code flows (many times, inconveniently, in order to deal with their particularities). The actual state of Bash is a product of a evolution, a code evolution. I mean, the first version of Bash uses more subshells*** than the actual one. This kind of inconsistency seems to be reasonable.

    ***if you want a proof, I can't give you. I've derived it from webpages, comments... I've read that statement somewhere sometime ago.

    – Daniel Bandeira Jul 23 '20 at 15:06

4 Answers4

47

The Advanced Bash-Scripting Guide is not always reliable and its example scripts contain out-dated practices such as using the effectively deprecated backticks for command substitution, i.e., `command` rather than $(command).

In this particular case, it’s blatantly incorrect.

The section on Shell Functions in the (canonical) Bash manual definitively states that

Shell functions are executed in the current shell context; no new process is created to interpret them.

  • 13
    "Advanced Bash-Scripting Guide is generally unreliable" Very true. – John1024 Aug 23 '16 at 23:31
  • 2
    Can you give references to support your first sentence? – Will Vousden Aug 24 '16 at 10:25
  • 6
    @WillVousden what would a reference look like here? A bunch of examples of the guide's technical shortfalls? A document where experts in the bash community have previously noted that it is unreliable? Would it help if a stackoverflow member with a gold badge in bash just agreed in a comment? :p – kojiro Aug 24 '16 at 11:13
  • @kojiro An overview of its problems and/or a more comprehensive list of examples would be good. Currently, the advice for Bash novices is that "it's bad, m'kay?" – Will Vousden Aug 24 '16 at 11:23
  • 3
    @WillVousden I don't think what you want exists in a reliable form itself. Mendel Cooper has updated and fixed issues with the guide in the past, but there is no public bug tracker or list of errata. (Perhaps that is the most damning statement I can make.) So when we find a flaw (perceived or real) all we can do is email the author and hope for the best. – kojiro Aug 24 '16 at 11:46
  • 3
    @WillVousden, ...if you want a history of how long the consensus in the freenode #bash channel has been that the ABS should be avoided, see http://wooledge.org/~greybot/meta/abs -- the second field in each line is the timestamp, and the first is the username; I'm going to hope that assertion that the usernames in question are very well-respected individuals suffices. – Charles Duffy Aug 24 '16 at 17:57
  • @WillVousden I wrote this answer quickly (before going to bed). I've since toned down the criticism of the Advanced Bash-Scripting Guide in the first sentence as my original wording was overly harsh and unjustified. – Anthony Geoghegan Aug 26 '16 at 10:00
  • "An overview of its problems and/or a more comprehensive list of examples would be good." -- ridiculous request. – Jim Balter Jul 13 '18 at 01:11
44

Curly brace functions will run within the calling shell process, unless they need their own subshell which is:

  • when you run them in the background with &
  • when you run them as a link in a pipeline

Redirections or extra env. variables won't force a new subshell:

hw(){
    echo hello world from $BASHPID
    echo var=$var
} 
var=42 hw >&2
echo $BASHPID  #unexports var=42 and restores stdout here

If you define the function with parentheses instead of curlies:

hw()(
  echo hello world from $BASHPID
)
hw 
echo $BASHPID

it will always run in a new process.

Command substitution $() also always creates processes in bash (but not in ksh if you run builtins inside it).

Petr Skocik
  • 28,816
  • I didn't know f() (...) is allowed. Are there any other definitions apart from {...} and (...)? In Bash, I'm not into others yet. –  Aug 23 '16 at 23:43
  • 1
    @tomas You can use the function hw { echo hello world; } syntax (no need for () if you type out function and you can specify redirections right after the final } or ) as in hw(){ echo error; } >&2. That's about it. – Petr Skocik Aug 23 '16 at 23:54
  • I knew these. Tx. –  Aug 23 '16 at 23:56
  • 2
    This is the answer I immediately thought about, and it is absolutely correct. It should be voted as the correct answer. f()(...) always execute an own shell, whilst f(){...} does not. – rexkogitans Aug 24 '16 at 08:22
  • 11
    NB bash functions accept any compound command, so foo() [[ x = x ]] is a valid function definition, too. However, if you look at the function with type foo you'll see that this is still syntactic sugar for foo() { [[ x = x ]]; }. The same is true of subshell functions: bar() ( : ) becomes bar() { ( : ); }. – kojiro Aug 24 '16 at 11:54
  • 1
    @kojiro nice +1. didn't know that – Petr Skocik Aug 24 '16 at 11:58
10

The command in question from that example looks like:

echo ${arrayZ[@]/%e/$(replacement)}

The example later states:

#    $( ... ) is command substitution.
#    A function runs as a sub-process.

Being charitable to ABS Guide, what they apparently meant to write is that the function runs inside a command substitution and the command inside a command substitution runs in a subshell.

John1024
  • 74,655
  • That's very misleading. Thanks for your interpretation. –  Aug 23 '16 at 23:38
  • 5
    @tomas "very misleading." Yes, very. In contrast to the ABS Guide, Greg's Wiki is an excellent source of advanced bash information. – John1024 Aug 23 '16 at 23:44
  • 1
    Cheers. What's your opinion about this one: http://wiki.bash-hackers.org/start ? –  Aug 23 '16 at 23:47
  • @tomas I have no first hand knowledge of that one. – John1024 Aug 23 '16 at 23:54
  • 2
    @tomas, ...my own opinion as to the bash-hackers wiki is that it's an excellent source. I haven't been through it as comprehensively as I have the Wooledge wiki, but it tends to be accurate and precisely written. – Charles Duffy Aug 24 '16 at 17:59
  • @CharlesDuffy Thanks. I know your skills from SO. –  Aug 24 '16 at 18:03
0

I'd note, that if executed in the background, a bash function will execute in a subshell. I only note this because I stumbled onto this question while checking for that fact.

[192.168.28.1 (1ae7468c) ~ 19:17:50]# function foo () { echo $BASHPID; }
[192.168.28.1 (1ae7468c) ~ 19:17:59]# foo
807477
[192.168.28.1 (1ae7468c) ~ 19:18:02]# foo
807477
[192.168.28.1 (1ae7468c) ~ 19:18:03]# foo &
[1] 1996783
1996783
[1]+  Done                    foo
[192.168.28.1 (1ae7468c) ~ 19:18:06]#