15

There are this two names: a subshell and a child-shell.

Yes, a child process will be started by any of this:

sh -c 'echo "Hello"'
( echo "hello" )
echo "$(echo "hello")
echo "hello" | cat

Are all equivalent and share the same name? Do all share the same properties?


POSIX has this definition:

A shell execution environment consists of ....

But the last paragraph of above link has this:

A subshell environment shall be created as a duplicate of the shell environment, except that signal traps that are not being ignored shall be set to the default action.

And specially:

Command substitution, commands that are grouped with parentheses, and asynchronous lists shall be executed in a subshell environment. Additionally, each command of a multi-command pipeline is in a subshell environment; ....

The sh -c 'echo "Hello"' is not included there, should that be called a subshell also?

2 Answers2

20

A subshell duplicates the existing shell. It has the same variables¹, the same functions, the same options, etc. Under the hood, a subshell is created with the fork system call²; the child process goes on to do what is expected of it while the parent waits (e.g., $(…)) or goes on with its life (e.g., … &) or otherwise does what is expected of it (e.g., … | …).

sh -c … does not create a subshell. It launches another program. That program happens to be a shell, but that's just a coincidence.  The program may even be a different shell (e.g., if you run sh -c … from bash, and sh is dash), i.e., a completely different program that just happens to have significant similarities in its behavior. Under the hood, launching an external command (sh or any other) calls the fork system call and then the execve system call to replace the shell program in the subprocess by another program (here sh).

¹ Including $$, but excluding some shell-specific variables such as bash and mksh's BASHPID.
² At least, that's the traditional and usual implementation. Shells can optimize the fork away if they can mimic the behavior otherwise. See What is the exact difference between a "subshell" and a "child process"?

Relevant man pages: fork(2), execve(2).

  • Thanks. What does running a bash script with bash shebang belong to? – Tim Feb 12 '16 at 00:44
  • @Tim Same thing as sh -c: that's a subprocess that coincidentally happens to be a shell. – Gilles 'SO- stop being evil' Feb 12 '16 at 00:53
  • (1) " launching an external command (sh or any other) calls the fork system call and then the execve system call to replace the shell program in the subprocess by another program (here sh)." Is it right that fork first creates a subshell and then execve replace the subshell with the external program? So in the two cases in your reply, a subshell is always created? (2) "A subshell that duplicates the existing shell." what does "that" mean? – Tim Feb 12 '16 at 01:32
  • (3) in bash -c <command>, after fork the shell and then execve bash -c <command> , a bash shell is created. Then are the system call used to run <command> again fork the bash shell and execve <command>? – Tim Feb 12 '16 at 01:42
  • @Gilles: So subshell is a child shell but not vice versa right? – cuonglm Feb 12 '16 at 05:25
  • @Gilles: Could you help with my question http://unix.stackexchange.com/questions/261595/do-a-bash-script-and-bash-c-command-run-in-a-subshell-environment ? Thanks. – Tim Feb 12 '16 at 08:01
  • 2
    @cuonglm “Child shell” is not a technical term with a specific meaning, unlike “subshell”. If it's a shell that's a child, then it's a child shell, following the usual rules of English. – Gilles 'SO- stop being evil' Feb 12 '16 at 12:36
3

A sub-shell environment does not need to live in a separate process, it just needs to duplicate the current execution environment. In ksh93 this is done by a virtual sub-shell mechanism that does not call fork(). This makes ksh93 very fast on archaic platforms like Win-DOS, as Win-DOS is extremely slow with forking.

sh -c cmd on the other side creates a new process with the default shell that does not need to be the same as your current interactive shell.

Even when sh and your current shell are identical, this does not duplicate the execution environment and thus does not create a sub-shell.

schily
  • 19,173