サブシェルとは

サブシェルとは、以下のサンプルコードで言うと、4〜7行目にわたって「()」で括られたリストを指します。

シェルスクリプトを実行する」とは、シェルが新たなシェルを子プロセスとしてメモリ上にロードし、その子プロセスが引数に指定されたスクリプトファイルを読み込み、ファイルに書かれた命令を順次実行する…ということですが、サブシェルは、その子プロセスから生成された孫プロセスで実行されます。

  1 #!/bin/bash
  2
  3 func()
  4 (
  5         ps -ef | grep `basename $0` | grep -v grep
  6         exit 10
  7 )
  8
  9 echo PID=$$
 10 ps -ef | grep `basename $0` | grep -v grep
 11
 12 echo "########"
 13 func
 14
 15 echo "########"
 16 ps -ef | grep `basename $0` | grep -v grep
 17
 18 exit 0

実行結果

$ echo $$
14367
$ bash ./hello.sh
PID=14471
yz2cm    14471 14367  0 03:38 pts/1    00:00:00 bash ./hello.sh
########
yz2cm    14471 14367  0 03:38 pts/1    00:00:00 bash ./hello.sh
yz2cm    14476 14471  0 03:38 pts/1    00:00:00 bash ./hello.sh
########
yz2cm    14471 14367  0 03:38 pts/1    00:00:00 bash ./hello.sh
$

元のシェルはPID=14367ですが、hello.shを実行するシェルはPID=14471としてforkされています。さらに、hello.sh内のサブシェルはPID=14476で起動しています。つまり、サブシェルは元の「bash ./hello.sh」とは別のプロセスとして起動しているため、サブシェル内6行目でexitコマンドを呼び出していますが、その子プロセスが終了するだけで、hello.shの処理は終了しません。