Linuxのシェルスクリプト実行方法と応用例

shell scriptはtext fileを「どのinterpreterで」「どのcurrent directoryとenvironmentで」「どの権限で」実行するかによって結果が変わります。bash script.sh、./script.sh、source script.shは同じではありません。初めてのscriptは構文検査、無害なsample入力、終了status確認を通してから実行します。

結論は「Bash scriptは明示的なshebangを置き、bash -nで構文を確認してからbash ./script.shまたは実行権限付きの./script.shで起動します。sourceはcurrent shellを変更する必要があるtrusted fileだけに限定します」です。

目次

三つの実行方法を混同しない

bash ./tool.shはBash programへfileを引数として渡すためfileのexecute bitは不要です。./tool.shはkernelがexecute permissionとshebangを確認します。source ./tool.shまたはdot builtinはcurrent shell contextでcommandを読み、variable、current directory、option、trapを呼び出し元へ残します。

  • scriptのinterpreterとBash version
  • script fileのowner・mode・hash
  • current directory、PATH、locale、timezone
  • 必要なargumentとinput fileのscope
  • 成功・0件・errorのexit status定義

実行前にfile内容をreviewし、download元とhashを確認します。sudo、curl pipe shell、credential、delete、network送信が含まれるscriptはtest環境でもowner承認なしに動かしません。line endingがCRLFだとshebang interpreter名へCRが混ざる場合があるためfileやod等で確認します。

対象スクリプトの先頭行、改行コード、実行権限、所有者、保存先、想定shell、引数を実行前に読みます。file、head、stat、bash -nを使い、Bash構文をshで起動していないか、Windows由来のCRLFでshebangが解釈できないかを確認します。カレントディレクトリに同名コマンドがあってもPATH検索へ頼らず、./script.shまたは絶対パスで対象を明示します。

最小scriptを構文検査して動かす

scriptへ#!/usr/bin/env bashまたは運用で固定したBash pathを選び、set optionは目的を理解して記述します。bash -nでparseし、test directoryとsample argumentで一回実行します。stdout、stderr、status、作成fileを確認してから本番scopeを一段階だけ広げます。

最小のBash script

#!/usr/bin/env bash
printf 'script=%s argc=%s\n' "$0" "$#"
printf 'first=%s\n' "$1"

argumentが必須なら先に件数を検証し、unquoted expansionを避けます。

構文だけを確認

bash -n -- ./tool.sh

commandを実行せずparse errorを確認しますが、logic errorやruntime failureは検出しません。

Bashへ明示的に渡す

bash -- ./tool.sh sample-input

execute bitがなくてもBashがreadできれば実行され、shebangより指定したBashが優先されます。

executableとして起動

./tool.sh sample-input
rc=$?
printf 'exit=%s\n' "$rc"

current directoryはPATH検索されないため./を付け、statusを直後に保存します。

subshellで環境影響を隔離

( cd ./test-fixture && ../tool.sh sample-input )
printf 'parent_dir=%s\n' "$PWD"

parent shellのcurrent directoryを変えないtestです。file変更等の外部影響はsubshellでも残ります。

動作確認は副作用のない小さなfixtureとtest directoryで行います。Bash用ならbash — ./script.sh argのようにinterpreterを明示する方法、実行権限と正しいshebangがあるなら./script.shを使う方法を分けます。source ./script.shは現在のshellへ変数、関数、working directory、optionを持ち込むため、環境設定用と確認できるスクリプト以外には使いません。

shebangとcommand検索の仕組み

shebangはexecutable fileをどのinterpreterへ渡すかを示します。/usr/bin/env bashはPATHからBashを探すためportableな場合がある一方、PATHが不正なら別実体を選びます。absolute path固定にもdistribution差があります。実行statusは最後のcommandまたは明示exitで決まり、stdout表示だけでは成功を判断できません。

  • bash script.shは指定Bashでfileを読みexecute bitを必須としない
  • ./script.shはexecute permissionとshebangが必要である
  • sourceはcurrent shellのvariable、directory、optionを変更し得る
  • bash -nはsyntaxを検査するがcommand runtimeはtestしない
  • script名だけの実行はPATH検索に依存しcurrent directoryを自動検索しない

bash script.shは新しいBash processがファイルを読み、./script.shはkernelがshebangのinterpreterへ渡します。sourceは新processを作らず現在のshellで実行するため、exit、cd、set、trap、readonlyの影響が呼び出し元へ残ります。位置引数、環境変数、標準入力、exit statusも呼び出し方式で扱いが変わるため、単に「動けば同じ」とみなしません。

untrusted scriptをsourceしない

third-party scriptをsource、sudo、root shellで試しません。production pathをsampleにせず、read-only fixtureと専用userを使います。scriptが作るfileのowner、mode、保存先を確認し、secretをargumentやxtraceへ出しません。変更操作にはbackupとrollbackを別に用意します。

  • bash実行とsourceを同じ効果と思う
  • current directoryをPATHへ無条件に追加する
  • bash -n成功を安全性確認とする
  • unquoted positional parameterでargument境界を壊す
  • scriptのexit statusを後続commandで上書きする

インターネットやメールから得たスクリプトを内容確認なしに実行・sourceしません。root権限、パッケージ変更、ファイル削除、ネットワーク送信、credential参照、cron登録が含まれないかを読みます。sudo bash scriptのように全体を高権限で動かす前に、必要操作を分離します。環境変数へ秘密を置く場合はxtraceやprocess環境からの露出を考え、テストでは模擬値を使います。

引数・environment・終了statusを検証する

空argument、spaceを含むargument、存在しないinput、permission不足、command不存在をtestします。stdout/stderr/status、作成file、parent directory、environment変化を記録し、同じBash versionとfixtureで再現できることを確認します。

  1. interpreter・script hash・mode・実行userを記録した
  2. bash -nとsample実行を通過した
  3. sourceを使わずparent shellへの副作用を制御した
  4. 成功・0件・errorのstatusを期待表で確認した

正常引数、引数なし、無効値、空文字、スペースを含む値、途中command失敗、signal、中断後cleanupをfixtureで確認します。stdout、stderr、exit status、作成・変更されたファイル、working directory、残存processを記録します。sourceを使う設定スクリプトなら、実行前後のset -o、trap、変数、関数、pwdを比較し、呼び出しshellを意図せず汚していないか確認します。

同じ条件で再実行できる方法を選ぶ

current shellへaliasやenvironmentを読み込む明確な目的がなければsourceを使いません。複数hostで動かすならBash version、dependency、PATHを仕様化します。root権限が必要と書かれたscriptは、必要な一commandへ権限を絞れるかreviewします。

一度だけBashスクリプトを動かすならbash — scriptで十分で、配布する実行物ならshebang、実行権限、依存command、usage、exit codeを整えます。現在shellへ設定を読み込む用途だけsourceを選びます。複雑なdata処理、並列実行、厳格な型、外部入力が多い処理は、Bashへ機能を足し続けずPython等の適切な言語とtest frameworkへ移す判断をします。

公式情報・参考資料

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次