$ echo $- himBH
シェルの動作は起動方式によって異なり、それに応じて読み込む設定ファイルの種類と順序も異なります。主な起動方式とその挙動について以下に整理します。
- ログインシェル(login shell)の起動 ログインシェルは、以下のような場面で実行されます:
- システム起動直後のコンソールログイン
- SSH経由でのリモートログイン(例:
ssh user@host)
この場合、以下に示す順序で設定ファイルが読み込まれます:
- /etc/environment → 環境変数の初期設定(PAM経由で適用される)
- /etc/profile → システム全体の初期化スクリプト
- 使用するシェルに応じて、
/.bash_profile、/.bash_login、~/.profile のいずれか(優先順位上位から順に存在Helら読み込み)
/.bash_profile内には通常、/.bashrcを明示的に呼び出す記述が含まれます。
さらに、~/.bashrcは /etc/bashrc を呼び出し、
/etc/bashrc は /etc/profile.d/*.sh を順次実行します。
- 明示的ログインシェル(bash -l または bash --login) 明示的にログインモードでシェルを起動した場合:
- /etc/profile,
- 当該ユーザーのログインシェル設定ファイル(~/.bash_profile など)
は読み込まれますが、/etc/environmentは読み込まれません。
- 非ログインシェル(インタラクティブ・ノンログイン) コマンドラインから bash とのみ入力して起動した場合など:
- 当該ユーザーの対話シェル設定(~/.bashrc)が読み込まれる
~/.bashrcは /etc/bashrc または /etc/bash.bashrc を読み込み、 その中で /etc/profile.d/*.sh が実行されます。
- タスクスケジューラ(cron)用シェル cronジョブ内では、デフォルトで非常に最小限の環境でスクリプトが実行されます:
- /etc/environment だけが読み込まれる
- /etc/profile, ~/.bashrc, /etc/bashrc などは読み込まれない
このため、cron内で環境変数やPATHを必要とするコマンドを実行する場合、明示的な読み込み処理が必要になります。
実際の動作確認例 以下は、各起動モードにおける設定ファイル読み込みの実際の出力例です(ログメッセージは各設定ファイル内の echo で出力):
# SSHログイン時(ログインシェル)
Last login: Fri Feb 7 17:40:49 2020 from 172.25.10.1
/etc/environment
/etc/profile
in ~/.bash_profile
in ~/.bashrc
in /etc/bashrc
# sudo su 後
# 環境をリロード(ただし $$ は変化しない)
/etc/environment
in root/.bashrc
in /etc/bashrc
# 単に "bash" で起動(非ログイン)
/etc/bashrc
in ~/.bashrc
in /etc/bashrc
# bash -l で起動(明示ログイン)
/etc/profile
in ~/.bash_profile
in ~/.bashrc
in /etc/bashrc
# サブシェル内 (echo a)
a
(設定ファイルは一切読み込まれない)
共通点と注意点
- ~/.bashrc → /etc/bashrc → /etc/profile.d/*.sh は、ほぼすべてのインタラクティブなシェル起動で共通して実行される
- cron実行では、上記の chain は含まれない
- /etc/environment は Hardcodedな設定であり、環境変数の逸脱を防ぐ目的でcron・sudo・ログイン時に限って読み込まれる
~/.bashrc VS cron の差異と解消方法 ローカルでは正常に動作するスクリプトが、cronで実行すると失敗する主な原因は、環境変数(特にPATH)の設定が読み込まれていないことです。
対応策1: /etc/environment に固定記述
- 全プロセスに影響する設定を置くべき場所
- 変更は再ログイン(または再sudo)で反映される
- 既存のシェルプロセスは再起動されないため、新しい環境変数を即座に参照しない点に注意
対応策2: スクリプト中で明示 source
#!/bin/bash
# スクリプト冒頭でオリジナル設定ファイルを読み込む
source ~/.myenv.sh
# または
. /etc/profile.d/custom.sh
# 以降、必要な環境設定が有効な状態で実行
この方法の利点:
- 設定ファイルをバージョン管理(git)可能
- ユニットテスト環境と本番環境を明確に切り替えられる
- cron・手動実行の差異を明示的に排除できる
反面、「 every script で毎回記述が必要」になること、および「権限管理・デプロイ手順」を意識する必要があります。
設定ファイルの読み込み順はシェルの実装やOS差異により変動するため、内容の確認には常に ${BASH_ENV}, ${ENV}, set +x オプション等による実航行の検証を推奨します。