bashで中括弧のグループコマンドをパイプでつなぐとサブシェルで実行されるので一応気をつける

Wed Apr 9 15:52:57 JST 2014 (modified: Sun Dec 22 12:15:39 JST 2019)
views: 4154, keywords:サブシェル,グループコマンド,bash, この記事は最終更新日が4年以上前のものです。

どうも。寝不足太郎上田です。細かい話が嫌いなのですが、調べる必要があり、調べたことを書きます。

{}で囲ったグループコマンドについてはシェルスクリプト本体と同じプロセスで動作するという記述がmanにあります。

ueda@remote:~$ man bash
   ...
    { list; }
    list is simply executed in the current shell environment. 
   ...

私の場合、グループコマンドはパイプに複数のコマンドを渡すときに使います。こんな感じで。

{
    echo ファイルのヘッダだよーん
    cat file
    echo ファイルのフッタだよーん
   } |
   cat -n 

ただ、こういうときはmanのとおりの同じプロセスでは動いていないんじゃないかと。なぜなら、パイプでグループコマンドをつなぐときに、別プロセスにする方がパイプを楽に繋げることができるからです。

ということで実験。bash4からBASHPIDという変数があって、これがサブシェルのプロセスIDを持っているので、こいつをechoしてみます。$$だとサブシェルでもシェルスクリプト本体のプロセスIDを保持し続けるのでこの実験はできません。

パイプでつながない場合

ueda@remote:~$ cat hoge.bash 
   #!/bin/bash
   
   echo 親: $BASHPID
   
   {
       echo 子: $BASHPID
   }
ueda@remote:~$ ./hoge.bash 
   親: 1671
   子: 1671

同じプロセスです。

パイプでつなぐ場合

ueda@remote:~$ cat hoge2.bash 
   #!/bin/bash
   
   echo 親: $BASHPID
   
   {
       echo 子: $BASHPID
   } | cat
ueda@remote:~$ ./hoge2.bash 
   親: 1706
   子: 1707

サブシェルですね。

ということは、次のように子供で定義した変数は親から見えません。こんな使い方しませんが、一応気をつけておいた方が良さそうです。

ueda@remote:~$ cat hoge2-2.bash 
   #!/bin/bash
   
   echo 親: $BASHPID
   
   {
       A=aaa
       echo 子: $BASHPID
   } | cat
   
   echo $A
   ueda@remote:~$ ./hoge2-2.bash 
   親: 1836
   子: 1837
    <- aaaと出てこない

丸括弧だと

次のようにデフォルトでサブシェルです。

ueda@remote:~$ cat hoge3.bash 
   #!/bin/bash
   
   echo 親: $BASHPID
   
   (
       echo 子: $BASHPID
   ) 
ueda@remote:~$ ./hoge3.bash 
   親: 1758
   子: 1759

ご相談

これは自明だからmanに書かないんでよいんですかね??in the current shell environmentというのがサブシェル云々の話とは違う話なのかな??どうしよう・・・。

気が小さいのでドキドキするだけで放置・・・。うーん。

ノート   このエントリーをはてなブックマークに追加 
 

prev:本日はこっちに書いた ---ささやかな自分プロジェクトの立ち上げ方。| techLIONブログ next:排他を実現するコマンドflock(1)の使い方メモ

やり散らかし一覧

記事いろいろ