bash-pro について
bash-proは、Bashによる自動化、CI/CD、運用スクリプトの作成とレビューを支援するスキルです。防御的なエラー処理、安全な入力処理、移植性、BatsやShellCheckによる検証を扱います。
主な機能
- 01厳密なエラー処理とトラップ
- 02安全な引数解析と入力検証
- 03移植性のあるファイル・プロセス操作
- 04BatsテストとShellCheck lint
- 05ログとスクリプト文書の整備
活用シーン
- 01スクリプトの危険な記述のレビュー
- 02CI/CD向けBash自動化の構築
- 03ファイル変更スクリプトの堅牢化
- 04対象プラットフォーム間でのテスト
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill bash-proインストール後、Claude Code で/bash-proを入力して読み込まれたか確認します。
詳細
このスキルを使用する場面
- 自動化、CI/CD、運用管理のための Bash スクリプトを作成またはレビューする場合
- シェルスクリプトの安全性と移植性を強化する場合
このスキルを使用しない場面
- Bash の機能を使わず、POSIX 専用のシェルが必要な場合
- 複雑なロジックのために、より高水準な言語が必要な場合
- Windows ネイティブのスクリプト作成(PowerShell)が必要な場合
手順
- スクリプトの入力、出力、失敗時の動作を定義します。
- 厳格モードと安全な引数解析を適用します。
- 防御的なパターンを使ってコアロジックを実装します。
- Bats と ShellCheck を使ってテストとリンティングを追加します。
安全性
- 入力は信頼できないものとして扱い、
evalや安全でないグロブの使用を避けます。 - 破壊的な操作の前に、ドライランモードを優先して使用します。
注力分野
- 厳格なエラー処理による防御的プログラミング
- POSIX 準拠とクロスプラットフォームの移植性
- 安全な引数解析と入力検証
- 堅牢なファイル操作と一時リソース管理
- プロセスのオーケストレーションとパイプラインの安全性
- 本番環境に適したログ記録とエラー報告
- Bats フレームワークによる包括的なテスト
- ShellCheck による静的解析と shfmt によるフォーマット
- 最新の Bash 5.x の機能とベストプラクティス
- CI/CD の統合と自動化ワークフロー
アプローチ
- 常に
set -Eeuo pipefailを使って厳格モードを有効にし、適切なエラートラップを設定します - 単語分割やグロブの問題を防ぐため、すべての変数展開を引用符で囲みます
for f in $(ls)のような安全でないパターンではなく、配列と適切な反復処理を優先します- Bash の条件式には
[[ ]]を使い、POSIX 準拠が必要な場合は[ ]を使用します getoptsと使用方法を示す関数を使って、包括的な引数解析を実装しますmktempとクリーンアップ用のトラップを使って、一時ファイルとディレクトリを安全に作成します- 出力形式を予測可能にするため、
echoよりprintfを優先します - 読みやすさを高めるため、バッククォートではなくコマンド置換の
$()を使います - タイムスタンプと設定可能な詳細度を備えた構造化ログを実装します
- スクリプトは冪等に設計し、ドライランモードをサポートします
- Bash 4.4 以降でエラー伝播を改善するため、
shopt -s inherit_errexitを使います - 空白文字による意図しない単語分割を防ぐため、
IFS=$'\n\t'を使用します - 必須の環境変数を
: "${VAR:?message}"で検証します - オプション解析は
--で終了し、安全な操作のためにrm -rf -- "$dir"を使います - 秘密情報を伏せたパスでのみ
set -xを許可します。トレースによって認証情報や引数が展開されます - サブプロセスの安全なオーケストレーションには、NUL 区切りを使う
xargs -0を使用します - コマンド出力から配列を安全に作成するには、
readarray/mapfileを使用します - 堅牢なスクリプトディレクトリ検出を実装します:
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" - NUL セーフなパターンを使用します:
find -print0 | while IFS= read -r -d '' file; do ...; done
互換性と移植性
- システム間の移植性のため、シバンには
#!/usr/bin/env bashを使います - スクリプトの開始時に Bash のバージョンを確認します:Bash 4.4 以降の機能を使う場合は
(( BASH_VERSINFO[0] > 4 || (BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 4) )) - 必要な外部コマンドの存在を検証します:
command -v jq &>/dev/null || exit 1 - プラットフォームの違いを検出します:
case "$(uname -s)" in Linux*) ... ;; Darwin*) ... ;; esac - GNU と BSD のツールの違いに対処します(例:
sed -iとsed -i '') - 対象となるすべてのプラットフォーム(Linux、macOS、BSD 系)でスクリプトをテストします
- スクリプトのヘッダーコメントに最低バージョン要件を記載します
- プラットフォーム固有の機能には代替実装を用意します
- 移植性のため、可能な場合は外部コマンドより Bash 組み込み機能を優先します
- POSIX 準拠が必要な場合は Bash 独自の機能を避け、使用する場合はその旨を記載します
可読性と保守性
- スクリプトでは明確さを優先し、短縮形の
-vではなく長形式のオプション--verboseを使用します - 一貫した命名規則を使います。関数や変数には snake_case、定数には UPPER_CASE を使用します
- 関連する関数を整理するため、コメントブロックでセクション見出しを追加します
- 関数は50行未満に保ち、それより長い場合は小さなコンポーネントに分割します
- 説明的なセクション見出しを使い、関連する関数をまとめます
check_fileではなくvalidate_input_fileのように、目的が分かる関数名を付けます- 一目で分からないロジックにはインラインコメントを追加し、自明なことは記述しません
- 一貫したインデントを維持します(スペース2個または4個を使い、タブとスペースを混在させないでください)
- 一貫性を保つため、開き波括弧は同じ行に置きます:
function_name() { - 関数内の論理的なブロックは空行で区切ります
- ヘッダーコメントに関数のパラメーターと戻り値を記述します
- マジックナンバーや文字列はスクリプトの先頭で名前付き定数に切り出します
安全性とセキュリティのパターン
- 意図しない変更を防ぐため、定数は
readonlyで宣言します - グローバルスコープを汚染しないよう、関数内のすべての変数に
localキーワードを使用します - 外部コマンドには
timeoutを実装します。curl --connect-timeout 5 --max-time 30 ...はネットワーク呼び出しを制限します。GNU timeout は macOS に同梱されていません - 操作の前にファイルのアクセス権を検証します:
[[ -r "$file" ]] || exit 1 - プロセス置換では pipefail が有効でも生成元の失敗が隠れることがあります。重要な入力では明示的に完了を待ち、結果を確認します
- ユーザー入力は、コマンドやファイル操作に使用する前にサニタイズします
- パターンマッチングで数値入力を検証します:
[[ $num =~ ^[0-9]+$ ]] - ユーザー入力に
evalを使用せず、動的なコマンドの構築には配列を使います - 機密情報を扱う操作では、制限の厳しい umask を設定します:(umask 077; touch "$secure_file")
- 認証、権限の変更、ファイルアクセスなど、セキュリティに関係する操作をログに記録します
- オプションと引数を区切るには
--を使用します:rm -rf -- "$user_input" - 環境変数は使用する前に検証します:
: "${REQUIRED_VAR:?not set}" - セキュリティ上重要なすべての操作で、終了コードを明示的に確認します
- 異常終了時にもクリーンアップが実行されるよう、
trapを使用します
パフォーマンスの最適化
- ループ内でサブシェルを避け、
for i in $(cat file)ではなくwhile readを使用します - 外部コマンドより Bash 組み込み機能を優先します。
testの代わりに[[ ]]、sedの代わりに${var//pattern/replacement}を使用します - 1回ずつ繰り返し実行するのではなく、処理をまとめます(例:複数の式を1つの
sedで実行します) - コマンド出力から効率よく配列を作成するには、
mapfile/readarrayを使用します - コマンド置換の繰り返しを避け、結果を一度だけ変数に保存します
- 計算には
exprではなく算術展開$(( ))を使用します - 書式付き出力には
echoよりも高速で信頼性の高いprintfを優先します - 繰り返し grep を実行するのではなく、検索には連想配列を使用します
- 大きなファイルはすべてをメモリに読み込まず、1行ずつ処理します
- 独立した処理を並列実行する場合は
xargs -Pを使用します
ドキュメントの標準
- 使用方法、オプション、例を表示する
--helpおよび-hフラグを実装します - スクリプトのバージョンと著作権情報を表示する
--versionフラグを用意します - よくある使用例をヘルプ出力に含めます
- すべてのコマンドラインオプションについて、目的を説明します
- 使用方法のメッセージで、必須引数と任意引数を明確に示します
- 終了コードを記載します。成功は0、一般的なエラーは1、特定の失敗には個別のコードを使用します
- 必要なコマンドとバージョンを列挙した前提条件のセクションを含めます
- スクリプトの目的、作成者、変更日を記載したヘッダーコメントブロックを追加します
- スクリプトが使用または必要とする環境変数を記載します
- よくある問題のトラブルシューティングのセクションをヘルプに用意します
- 特殊なコメント形式から
shdocでドキュメントを生成します - システムに統合するため、
shellmanで man ページを作成します - 複雑なスクリプトでは Mermaid または GraphViz を使ったアーキテクチャ図を含めます
モダンな Bash の機能(5.x)
- すべての Bash 5.x バージョンで変換、shopt オプション、リダイレクトの動作が共通していると仮定せず、必要な各機能を対象の Bash マニュアルで確認してください。
EPOCHREALTIMEはマイクロ秒単位の精度でエポック秒を返します。これは壁時計であり、単調増加するベンチマーク用タイマーではありません。- モダンな機能を使用する前にバージョンを確認してください:
(( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 2) )) - シェル用に引用符で囲んだ出力には
${parameter@Q}を使用してください(Bash 4.4+) - エスケープシーケンスの展開には
${parameter@E}を使用してください(Bash 4.4+) - プロンプトの展開には
${parameter@P}を使用してください(Bash 4.4+) - 代入形式には
${parameter@A}を使用してください(Bash 4.4+) - バックグラウンドジョブのいずれかを待つには
wait -nを使用してください(Bash 4.3+) - カスタム区切り文字には
mapfile -d delimを使用してください(Bash 4.4+)
CI/CD との統合
- GitHub Actions:インライン注釈には
shellcheck-problem-matchersを使用してください - Pre-commit フック:
shellcheck、shfmt、checkbashismsを使って.pre-commit-config.yamlを設定してください - マトリックステスト:Linux と macOS で Bash 4.4、5.0、5.1、5.2 を使ってテストしてください
- コンテナテスト:再現可能なテストには公式の bash:5.2 Docker イメージを使用してください
- CodeQL:該当する場合は、サポート対象言語の解析を使用してください。汎用の Bash アナライザーではありません
- Actionlint:シェルスクリプトを使用する GitHub Actions ワークフローファイルを検証してください
- 自動リリース:バージョンにタグを付け、変更履歴を自動生成してください
- カバレッジレポート:テストカバレッジを追跡し、後退があれば失敗させてください
- ワークフローの例:
shellcheck *.sh && shfmt -d *.sh && bats test/
セキュリティスキャンと強化
- SAST:シェル固有の脆弱性に対応するカスタムルールを設定して Semgrep を統合してください
- シークレット検出:認証情報の漏えいを防ぐため、
gitleaksまたはtrufflehogを使用してください - サプライチェーン:外部から読み込むスクリプトのチェックサムを検証してください
- サンドボックス化:信頼できないスクリプトは、まずデータとして調査してください。コンテナだけでは、実行が許可されることも、ネットワーク/マウント/シークレットが隔離されることもありません
- SBOM:コンプライアンスのために依存関係と外部ツールを文書化してください
- セキュリティリンティング:セキュリティ重視のルールを有効にして ShellCheck を使用してください
- 権限分析:不要な root/sudo 要件がないかスクリプトを監査してください
- 入力のサニタイズ:すべての外部入力を許可リストに照らして検証してください
- 監査ログ:セキュリティに関わるすべての操作を syslog に記録してください
- コンテナセキュリティ:スクリプトの実行環境に脆弱性がないかスキャンしてください
可観測性とロギング
- 構造化ロギング:ログ集約システム向けに JSON を出力してください
- ログレベル:設定可能な詳細度で DEBUG、INFO、WARN、ERROR を実装してください
- Syslog との統合:システムログとの統合には
loggerコマンドを使用してください - 分散トレーシング:複数のスクリプトにまたがるワークフローを関連付けるため、トレース ID を追加してください
- メトリクスのエクスポート:監視用に Prometheus 形式のメトリクスを出力してください
- エラーのコンテキスト:秘匿化した場所/ステータスを含めてください。環境変数や展開後のシークレットを含むコマンドを絶対に出力しないでください
- ログローテーション:長時間実行されるスクリプト用にログファイルのローテーションを設定してください
- パフォーマンスメトリクス:実行時間、リソース使用量、外部呼び出しのレイテンシを追跡してください
- 例:
log_info() { logger -t "$SCRIPT_NAME" -p user.info "$*"; echo "[INFO] $*" >&2; }
品質チェックリスト
- スクリプトは、抑制を最小限にして ShellCheck の静的解析に合格する
- コードは標準オプションを使った shfmt で一貫した形式に整えられている
- エッジケースを含め、Bats による包括的なテストカバレッジがある
- すべての変数展開が適切に引用符で囲まれている
- エラー処理がすべての失敗モードを対象とし、分かりやすいメッセージを表示する
- EXIT トラップを使って一時リソースが適切にクリーンアップされる
- スクリプトが
--helpに対応し、分かりやすい使用方法を示す - 入力検証によってインジェクション攻撃を防ぎ、エッジケースに対応する
- スクリプトが対象プラットフォーム(Linux、macOS)間で移植可能である
- 想定されるワークロードとデータサイズに対して、パフォーマンスが十分である
出力
- 防御的プログラミングを実践した、本番環境対応の Bash スクリプト
- bats-core または shellspec を使用した、TAP 出力対応の包括的なテストスイート
- 自動テスト用の CI/CD パイプライン設定(GitHub Actions、GitLab CI)
- shdoc で生成したドキュメントと、shellman で生成した man ページ
- 再利用可能なライブラリ関数と依存関係管理を備えた、構造化されたプロジェクト構成
- 静的解析設定ファイル(.shellcheckrc、.shfmt.toml、.editorconfig)
- 重要なワークフローのパフォーマンスベンチマークとプロファイリングレポート
- SAST、シークレットスキャン、脆弱性レポートによるセキュリティレビュー
- トレースモード、構造化ログ、可観測性を備えたデバッグユーティリティ
- Bash 3→5 へのアップグレードとレガシー環境のモダナイズに関する移行ガイド
- パッケージ配布設定(Homebrew formula、deb/rpm 仕様)
- 再現可能な実行環境用のコンテナーイメージ
必須ツール
静的解析とフォーマット
- ShellCheck:
enable=allとexternal-sources=trueを設定した静的解析ツール - shfmt: 標準設定(
-i 2 -ci -bn -sr -kp)を使用するシェルスクリプトフォーマッター - checkbashisms: 移植性を分析するため、Bash 固有の構文を検出します
- Semgrep: シェル固有のセキュリティ問題に対応するカスタムルールを備えた SAST
- CodeQL: 対応言語/Actions の解析に使用します。単独の Bash には ShellCheck を使用してください
テストフレームワーク
- bats-core: 最新機能を備え、活発に開発されている Bats の保守版フォーク
- shellspec: 豊富なアサーションとモック機能を備えた BDD スタイルのテストフレームワーク
- shunit2: シェルスクリプト向けの xUnit スタイルのテストフレームワーク
- bashing: モック機能とテスト分離をサポートするテストフレームワーク
最新の開発ツール
- bashly: コマンドラインアプリケーション構築用の CLI フレームワークジェネレーター
- basher: 依存関係管理用の Bash パッケージマネージャー
- bpkg: npm のようなインターフェースを備えた代替 Bash パッケージマネージャー
- shdoc: シェルスクリプトのコメントから Markdown ドキュメントを生成します
- shellman: シェルスクリプトから man ページを生成します
CI/CD と自動化
- pre-commit: 複数言語に対応したコミット前フックのフレームワーク
- actionlint: GitHub Actions ワークフローのリンター
- gitleaks: 認証情報の漏えいを防ぐシークレットスキャンツール
- Makefile: lint、format、test、release の各ワークフローを自動化します
避けるべきよくある落とし穴
for f in $(ls ...)は単語分割や glob 展開のバグを引き起こします(find -print0 | while IFS= read -r -d '' f; do ...; doneを使用してください)- 変数展開を引用符で囲まないと、予期しない動作につながります
- 複雑な処理で適切なエラートラップを設定せずに
set -eに依存すること - データ出力に
echoを使用すること(信頼性の高いprintfを推奨します) - 一時ファイルやディレクトリのクリーンアップ用トラップを設定しないこと
- 安全でない配列の初期化(コマンド置換ではなく
readarray/mapfileを使用してください) - バイナリセーフなファイル処理を考慮しないこと(ファイル名には常に NUL 区切りを検討してください)
依存関係管理
- パッケージマネージャー: シェルスクリプトの依存関係のインストールには
basherまたはbpkgを使用します - ベンダー化: 再現可能なビルドのため、依存関係をプロジェクトにコピーします
- ロックファイル: 使用する依存関係の正確なバージョンを記録します
- チェックサム検証: 外部から読み込むスクリプトの整合性を検証します
- バージョンの固定: 破壊的変更を防ぐため、依存関係を特定のバージョンに固定します
- 依存関係の分離: 依存関係のセットごとに別々のディレクトリを使用します
- 更新の自動化: Dependabot または Renovate で依存関係の更新を自動化します
- セキュリティスキャン: 既知の脆弱性がないか依存関係をスキャンします
- 例:
basher install username/repo@versionまたはbpkg install username/repo -g
高度なテクニック
- エラーコンテキスト:デバッグには
trap 'echo "Error at line $LINENO: exit $?" >&2' ERRを使用します - 安全な一時ファイルの扱い:
tmpdir=$(mktemp -d) || exit 1; trap 'rm -rf -- "$tmpdir"' EXIT - バージョン確認:新しい機能を使用する前に
(( BASH_VERSINFO[0] >= 5 ))で確認します - バイナリセーフな配列:
readarray -d '' files < <(find . -print0) - 関数の戻り値:関数から複雑なデータを返すには
declare -g resultを使用します - 連想配列:複雑なデータ構造には
declare -A config=([host]="localhost" [port]="8080")を使用します - パラメーター展開:
${filename%.sh}で拡張子を削除し、${path##*/}でベース名を取得し、${text//old/new}ですべて置換します - シグナル処理:正常に終了するには
trap cleanup_function SIGHUP SIGINT SIGTERMを使用します - コマンドのグループ化:リダイレクトを共有するには
{ cmd1; cmd2; } > output.logを、分離のためにサブシェルを使うには( cd dir && cmd )を使用します - コプロセス:双方向パイプには
coproc proc { cmd; }; echo "data" >&"${proc[1]}"; read -u "${proc[0]}" resultを使用します - ヒアドキュメント:
cat <<-'EOF'は先頭のタブを削除し、引用符は展開を防ぎます - プロセス管理:バックグラウンドジョブの終了を待つには
wait $pidを、バックグラウンドの PID を一覧表示するにはjobs -pを使用します - 条件付き実行:
cmd1 && cmd2はcmd1が成功した場合にのみcmd2を実行し、cmd1 || cmd2はcmd1が失敗した場合にcmd2を実行します - ブレース展開:
touch file{1..10}.txtを使うと、複数のファイルを効率よく作成できます - 名前参照変数:
declare -n ref=varnameは別の変数への参照を作成します(Bash 4.3+) - エラートラップの改善:包括的なエラー処理には
set -Eeuo pipefail; shopt -s inherit_errexitを使用します - 並列実行:CPU コア数に基づいて並列処理するには
xargs -P $(nproc) -n 1 commandを使用します - 構造化出力:JSON の生成には
jq -n --arg key "$value" '{key: $key}'を使用します - パフォーマンスのプロファイリング:詳細なリソース使用状況には
time -vを、カスタムの計測にはTIMEFORMATを使用します
参考資料と詳しい情報
スタイルガイドとベストプラクティス
- Google Shell Style Guide - 引用符、配列、シェルを使うタイミングを網羅した包括的なスタイルガイド
- Bash Pitfalls - よくある Bash の間違いと、その回避方法をまとめた一覧
- Bash Hackers Wiki - Bash の包括的なドキュメントと高度なテクニック
- Defensive BASH Programming - 最新の防御的プログラミングのパターン
ツールとフレームワーク
- ShellCheck - 静的解析ツールと充実した Wiki ドキュメント
- shfmt - 詳細なフラグのドキュメントを備えたシェルスクリプトフォーマッター
- bats-core - メンテナンスされている Bash テストフレームワーク
- shellspec - シェルスクリプト向けの BDD スタイルのテストフレームワーク
- bashly - 最新の Bash CLI フレームワークジェネレーター
- shdoc - シェルスクリプト向けのドキュメントジェネレーター
セキュリティと高度なトピック
- Bash Security Best Practices - セキュリティを重視したシェルスクリプトのパターン
- Awesome Bash - Bash のリソースとツールを厳選した一覧
- Pure Bash Bible - 外部コマンドを使わない Bash の代替手段集
例
#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
task_tmpdir=$(mktemp -d) || exit 1
trap 'rm -rf -- "$task_tmpdir"' EXIT
printf '%s\n' 'example' > "$task_tmpdir/input.txt"
[[ -s "$task_tmpdir/input.txt" ]] || exit 1
クリーンアップの設定より前にディレクトリが作成されます。削除する前に、許可されたパスを引用符で囲むか検証してください。-- はオプションの解析を停止しますが、誤った絶対パスを削除することは防げません。厳格モードと ERR トラップでも、あらゆる失敗状況を捕捉できるわけではありません。
制限事項
- タスクが上記の説明にある範囲に明確に該当する場合にのみ、このスキルを使用してください。
- 出力を、環境固有の検証、テスト、または専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全上の境界、または成功基準が不足している場合は、作業を中断して確認を求めてください。
主な言語のサポート:CodeQL がサポートする言語。
コメント
Markdown 対応