shellとは何か? コマンドインタプリタを解説する
shellは、入力したコマンドを受け取り、解釈し、オペレーティングシステムに実行を依頼するプログラムです。
CI scriptの各行、workflowの各run:ブロックは、shellに渡されます。shellはテキストを解析し、変数やワイルドカードを展開し、適切なプログラムを起動し、それらが成功したかどうかを報告します。shellを理解すると、どのshellが実行するか、どのオプションが設定されているかによってscriptの動作が異なる理由が分かります。
shellがすること
shellは入力行を読み取り、コマンドとその引数に分割し、展開 (変数、glob、コマンド置換) を行い、プログラムを起動して終了を待ちます。これは対話的なプロンプトであると同時にスクリプト言語でもあります。
対話的な使用とscript化された使用
端末に向かうとき、shellは一度に1つのコマンドを求めます。scriptを実行するときは、ファイルの上から下へコマンドを読み取ります。CIはほぼ常にscript化された非対話モードを使い、これはローカルのプロンプトとわずかに異なる動作をします。
一般的なshell
- sh: 最小限のPOSIX shell、最小公倍数的存在。
- bash: 最も一般的なLinux shell、多くの追加機能を持つ。
- zsh: 現代のmacOSのデフォルト、ほとんどのscriptでbash互換。
- PowerShell: Windowsランナーのデフォルトshell。
なぜCIでshellが重要か
ノートPCで動作するworkflowのstepが、異なるshell、または異なるオプションの同じshellがscriptを解析したためにCIで失敗することがあります。どのshellが実行しどのflagが設定されているかを知ることが、不安定なscriptをデバッグする第一歩です。
簡単な例
cp build/*.js dist/という行は、オペレーティングシステムが直接理解するものではありません。shellはまずbuild/*.jsを一致するファイルのリストに展開し、そのリストでcpを呼び出します。shellがなければ展開もありません。
管理型ランナーでのshell
Latchkeyのような管理型ランナーでは、各stepが予測可能なデフォルトで新しいshellを起動するので、scriptは毎回同じ動作をします。この一貫性は、失敗を「自分のマシンでは動く」という謎ではなく、再現可能なものにします。
重要なポイント
- shellはコマンドを解釈し、オペレーティングシステムに実行を依頼します。
- CIはshellを非対話的なscript化モードで実行し、これはプロンプトと異なる場合があります。
- どのshellとどのオプションがアクティブかが、CI scriptの動作を直接左右します。