ITエンジニアによるITエンジニアのためのブログ

ログイン、対話型シェルの組み合わせとスタートアップファイル

Linuxのシェルには、起動方法によってログインシェル非ログインシェルか、対話型シェル非対話型シェルかの区別があります。この組み合わせにより、シェルの起動パターンは4つに分類されます。

重要なのは、それぞれのパターンで読み込まれる設定ファイル(.profile.bashrcなど)が異なるという点です。この違いを理解していないと、環境変数やエイリアスなどを意図しない場所に設定してしまい、「設定したはずなのに反映されない」といった問題の原因になります。

この記事では、各シェルの種類の違いを明確にし、4つの起動パターンを解説します。さらに、各パターンでどの設定ファイルが読み込まれ、何を記述すべきかを具体的に説明します。

本記事では、シェルは bash、LinuxディストリビューションはUbuntuを前提として解説します。

目次

  1. ログインシェルと非ログインシェル
  2. 対話型シェルと非対話型シェル
  3. シェルの4つの組み合わせパターン
  4. 読み込まれるスタートアップファイル
  5. 各スタートアップファイルに記述すべき内容
  6. まとめ

1. ログインシェルと非ログインシェル

シェルのプロセスが「ログインシェル」かどうかは、主にその起動方法によって決まります。bashのmanページ(man bash)によると、ログインシェルは以下のいずれかの条件を満たすものです。

A login shell is one whose first character of argument zero is a -, or one started with the –login option.

(日本語訳:ログインシェルとは、引数0の最初の文字が - であるか、--login オプション付きで起動されたシェルのことである。)

a) 引数$0の先頭がハイフン (-)

シェルの特殊変数 $0 には実行ファイル名が格納されます。この値の先頭文字がハイフン (-) の場合、そのシェルはログインシェルです。

# 現在のシェルの$0を確認
echo $0

# 実行結果の例
-bash  # 先頭がハイフンなのでログインシェル
bash   # 先頭がハイフンではないので非ログインシェル

tty(仮想コンソール)やSSHでサーバーに接続した際に起動するシェルは、この方法でログインシェルとして起動します。また、GNOME Terminalなどの端末エミュレータも、設定で「ログインシェルとしてコマンドを実行する」を有効にすると、$0の先頭にハイフンが付与されます。

b) --login オプションで起動

もう一つの条件は、--login オプションを付けてシェルを起動することです。

# Bash
bash --login

この方法で起動した場合、$0 の値は bash のままで先頭にハイフンは付きませんが、プロセスとしてはログインシェルとして扱われます。

2. 対話型シェルと非対話型シェル

「対話型シェル」とは、ユーザーがコマンドをキーボードから入力し、その結果を画面で確認する、というような対話的な操作が可能なシェルです。man bash によると、対話型シェルは以下の条件で起動されます。

An interactive shell is one started without non-option arguments … and without the -c option whose standard input and error are both connected to terminals … or one started with the -i option.

(日本語訳:対話型シェルとは、非オプション引数や -c オプションなしで起動され、標準入出力が端末に接続されているもの、または -i オプション付きで起動されたものである。)

それぞれの定義を見ていきます。

a) 引数や-cオプションなしで起動

シェルスクリプトのファイル名を引数として渡したり、-cオプションでコマンド文字列を渡したりせず、単純に bash と実行した場合、対話型シェルになります。

# 対話型シェルとして起動
bash

# --loginオプションを付けても対話型
bash --login

一方、以下のようにスクリプトやコマンドを指定すると非対話型シェルになります。

反対に、以下のシェル起動コマンドはオプション引数以外を指定しているため、対話型シェルではなく非対話型シェルです。

# スクリプトを実行するため、非対話型
bash test.sh

# -c オプションでコマンドを実行するため、非対話型
bash -c 'ls -l'

b) -i オプションで起動

-i (interactive) オプションを付けて起動すると、強制的に対話型シェルになります。

# スクリプト実行だが、-i 付きなので対話型
bash -i test.sh

# コマンド実行だが、-i 付きなので対話型
bash -ic ls

現在のシェルが対話型かどうかの見分け方

現在のシェルが対話型かどうかは、特殊変数 $- の値で確認できます。この変数に i が含まれていれば対話型です。

# 対話型シェルの場合
echo $-
himBHs # 'i'が含まれている

# 非対話型シェルの場合(例: コマンド実行)
bash -c 'echo $-'
hBc # 'i'が含まれていない

3. シェルの4つの組み合わせパターン

「ログイン/非ログイン」と「対話型/非対話型」は独立した概念であり、以下の4つの組み合わせが存在します。

対話型非対話型
ログインシェル① 対話型ログインシェル② 非対話型ログインシェル
非ログインシェル③ 対話型非ログインシェル④ 非対話型非ログインシェル

① 対話型ログインシェル

ユーザーがシステムにログインして直接操作する、最も一般的なシェルです。

  • ttyやSSHでログインした直後のシェル
  • bash --login を実行した場合
  • su - usersudo -i を実行した場合

② 非対話型ログインシェル

ログインはするものの、ユーザーが直接コマンドを入力しないシェルです。

  • bash --login test.sh のように、ログインオプションを付けてスクリプトやコマンドを実行した場合。
  • sudo -i commandsu - commandのように、ログインオプションを付けてコマンド実行した場合
  • グラフィカルデスクトップ環境へのログイン時(環境変数を設定するために内部的に起動される)

③ 対話型非ログインシェル

ログイン後、新しいシェルを起動した場合などです。

  • 端末エミュレータで bash と入力して新しいシェルを起動した場合
  • su user のように - なしでユーザーを切り替えた場合
  • sudo -s -u userのように、シェルオプションでユーザーを切り替えた場合
  • docker exec -it my-container bash でコンテナに入る場合
  • GNOME Terminalでログインシェルとして起動しない場合

④ 非対話型非ログインシェル

シェルスクリプトの実行など、自動化処理で最もよく使われるシェルです。

  • bash test.sh でスクリプトを実行した場合
  • bash -c 'command'でコマンドを実行した場合
  • ssh user@host "command" でリモートコマンドを実行した場合
  • sudo commandsu -c "command" でコマンドを実行した場合
  • cronジョブで実行されるシェルスクリプト
  • docker exec my-container commandでコマンド実行した場合

4. 読み込まれるスタートアップファイル

シェルの起動パターンによって、読み込まれる設定ファイル(スタートアップファイル)が異なります。

ログインシェル (対話型・非対話型共通)

ログインシェルが起動すると、まず /etc/profile が読み込まれます。その後、以下のファイルが 最初に見つかった1つだけ 読み込まれます。

  1. ~/.bash_profile
  2. ~/.bash_login
  3. ~/.profile

ポイント: 多くのディストリビューションでは、~/.profile~/.bash_profile の中で、~/.bashrc を読み込むように設定されています。これは bash の仕様ではなく、あくまで設定によるものです。

また、ログインシェルを exit で終了する際には ~/.bash_logout が読み込まれます。

対話型非ログインシェル

このパターンの場合、以下のファイルが読み込まれます。

  • /etc/bash.bashrc (システム全体の設定)
  • ~/.bashrc (ユーザー個別の設定)

非対話型非ログインシェル

デフォルトでは、どの設定ファイルも読み込みません

ただし、環境変数 BASH_ENV にファイルのパスが設定されている場合、そのファイルが読み込まれます。

例外: ssh user@host "command" のようにリモートコマンドを実行する場合は、非対話型非ログインシェルですが、bash の仕様により /etc/bash.bashrc~/.bashrc が読み込まれます。(※ 厳密には sshd の設定に依存しますが、多くの環境でこのように動作します。)

5. 各スタートアップファイルに記述すべき内容

設定をどのファイルに書くべきか、その指針を示します。

ログインシェル用ファイル (~/.profile など)

ログイン時に一度だけ設定すればよい項目を記述します。ここで設定した内容は、その後に起動されるすべての子プロセス(非ログインシェル含む)に引き継がれます。

  • 環境変数: PATH の追加、EDITORLANG の設定など。
  • 自作の環境変数は export を付けて子プロセスに引き継がれるようにします。
  • セッション全体の設定: umask の設定など。
# ~/.profile の設定例

# PATHはexport済みなので再exportは不要
PATH="$HOME/bin:$PATH"

# デフォルトエディタを子プロセスにも適用
export EDITOR=vim

# デフォルトのファイルパーミッションを指定
umask 022

対話型シェル用ファイル

対話型シェル用のスタートアップファイルは、/etc/bash.bashrc~/.bashrcです。

ここには対話的な操作を便利にするための設定を記述します。シェルを起動するたびに読み込まれるため、対話型シェルでのみ有効にしたい設定に適しています。

  • エイリアス: alias ll='ls -alF' など。
  • シェル関数: よく使うコマンドをまとめた関数など。
  • プロンプト設定: PS1 のカスタマイズ。
  • 対話型シェルでのみ意味を持つ変数: HISTSIZE (コマンド履歴の保存数)など。
# ~/.bashrc の設定例

# コマンド履歴の保存件数
HISTSIZE=1000
HISTFILESIZE=2000

# シェルプロンプトのカスタマイズ
PS1='[\u@\h \W]\$ '

# よく使うコマンドのエイリアス
alias ll='ls -alF'
alias la='ls -A'

エイリアスや関数は定義したシェルでしか有効でなく、環境変数のように子プロセスに引き継げないため、一度しか読み込まれないログインシェル用スタートアップファイルではなく、シェルを起動する度に読み込まれる対話型シェル用スタートアップファイルに記述するのが適切です。

なお、対話型シェル用スタートアップファイルはログインシェル用スタートアップファイル内で明示的にソース(source)されていることが一般的なため、ログインシェルでも読み込まれることが多いです。

# ~/.profile
if [ -n "$BASH_VERSION" ]; then
    # .bashrcが存在したら読み込む
    if [ -f "$HOME/.bashrc" ]; then
	. "$HOME/.bashrc"
    fi
fi

6. まとめ

シェルの4つのパターンと、それぞれが読み込む設定ファイルを理解することは、Linux環境を効率的にカスタマイズする上で非常に重要です。

以下の表に要点を示します。

対話型非対話型
ログインシェル
起動例: ssh, su -

設定ファイル: /etc/profile~/.profile (または ~/.bash_profile 等)
起動例: ssh, su -

設定ファイル: /etc/profile~/.profile (または ~/.bash_profile 等)
非ログインシェル起動例: bash, su

設定ファイル: /etc/bash.bashrc~/.bashrc
起動例: bash script.sh, cron

設定ファイル: 通常なし (BASH_ENVで指定可)。
ssh host "cmd"では/etc/bash.bashrc~/.bashrc