Skip to content
Latchkey

subshellとは何か?分離のための子shell

subshellは、環境の独自のコピーでコマンドのグループを実行する子shell processで、その内部の変更は親に影響しません。

shellは時々、コマンドのグループを分離して実行するために、自身の子コピーであるsubshellを生成します。subshell内での変数の変更やディレクトリの変更は、それが終了すると消えます。これはスコープの制御に役立ちますが、変数がなぜか定着しないときの典型的な混乱の原因でもあります。

subshellとは何か

subshellは、現在のshellからforkされた別のshell processです。親の環境を継承しますが、変数の設定やディレクトリの変更など、それが行う変更はすべてその内部にとどまります。

subshellが作られる方法

  • 括弧: ( cd build && make )はsubshellで実行されます。
  • pipeline: |の各側は独自のsubshellで実行されることがあります。
  • command substitution: $(...)はコマンドをsubshellで実行します。

分離の効果

subshellは環境の独自のコピーを持つため、( cd /tmp )は戻った後に親のディレクトリを変更しません。この分離が目的ですが、変更が残ることを期待する人を驚かせます。

よくある落とし穴

pipeされたループ内で設定された変数は、ループがsubshellで実行されたため、残らないことがあります。find . | while read f; do count=$((count+1)); doneは、親でcountを変更しないままにすることがあります。

CIにおけるsubshell

CIスクリプトでは、subshellはサブディレクトリでbuildを実行するなど、外側のshellを汚さずにコマンドをグループ化するのに役立ちます。しかし後でsubshell内で設定された変数に依存すると、それは空になり、見つけにくいバグを引き起こします。

マネージドrunnerでの予測可能なスクリプト

Latchkeyのrunnerでは、ディレクトリ変更のスコープを制限するためにsubshellを使うと、ステップの残りをきれいに保てます。ただし、後で必要になる値はsubshell内で設定するのではなく、親shellにキャプチャする必要があることを忘れないでください。

重要なポイント

  • subshellは、環境の分離されたコピーでコマンドを実行する子shellです。
  • cdや変数などsubshell内の変更は、親には残りません。
  • 括弧、pipeline、$(...)はすべてスクリプト内でsubshellを作成します。

関連ガイド