ログインシェルと非ログインシェルの違いは?


318

対話型シェルと非対話型シェルの基本的な違いを理解しています。しかし、ログインシェルと非ログインシェルを正確に区別するものは何ですか?

非ログインインタラクティブシェルの使用例はありますか?


45
この質問は、「ログインシェルと非ログインシェルを区別する必要があるのはなぜですか?」と表現されていると思います。ウェブ上の多くの場所では、それぞれが読み込むスタートアップファイルの観点から、違いが何であるかをすでに示しています。しかし、どれも満足のいく説得力のある方法で「なぜ」に答えているようには見えません。どちらか一方の動作が絶対に望ましくないユースケースの例は素晴らしいでしょう。
カル

2
@Kalこれは別の質問である必要があります。ここでの答えは実際にはそれをカバーしていません。編集:実際には、ここにあります:なぜログインシェル上のログインシェル?
スキッピールグラングロウ

回答:


304

ログインシェルは、対話型セッションにログインするときにユーザーIDで実行される最初のプロセスです。ログインプロセスは、シェルに慣例に従ってログインシェルとして振る舞うように指示します:引数0(通常はシェル実行可能ファイルの名前)を-追加し、文字を追加します(たとえば-bash、通常はbash。環境変数の設定など:/etc/profileおよび~/.profile従来のBourneシェルの場合~/.bash_profile、bash †の場合/etc/zprofile~/.zprofilezsh †の場合/etc/csh.login~/.logincshの場合など。

テキストコンソールにログインするか、SSH経由で、またはを使用してログインsu -すると、対話型ログインシェルが表示されます。(Xディスプレイマネージャーで)グラフィカルモードでログインすると、ログインシェルは取得されず、セッションマネージャーまたはウィンドウマネージャーが取得されます。

非対話型のログインシェルを実行することはまれですが、プロファイルファイルの読み取りを手配するために、ディスプレイマネージャーを使用してログインするときに、Xの設定によっては実行されない場合があります。他の設定(これはディストリビューションとディスプレイマネージャーに依存します)を読み取り/etc/profile~/.profile明示的に読み取るか、読み取らないでください。非対話型ログインシェルを取得する別の方法は、端末ではない標準入力を介して渡されるコマンドを使用してリモートでログインすることですssh example.com <my-script-which-is-stored-locally(たとえばssh example.com my-script-which-is-on-the-remote-machine、非対話型、非ログインシェルを実行します)。

既存のセッションのターミナル(画面、Xターミナル、Emacsターミナルバッファ、別のシェル内のシェルなど)でシェルを起動すると、対話型の非ログインシェルになります。そのシェルは、シェルの設定ファイル(読むかもしれない~/.bashrcとして呼び出さbashのためのbash/etc/zshrcおよび~/.zshrczshのため、/etc/csh.cshrcおよび~/.cshrcCSHのため、で示されるファイルENVとして呼び出されたときに、このようなダッシュ、kshの、およびbashのようにPOSIX / XSI準拠のシェルの変数をsh$ENV設定している場合と、~/.mkshrcmkshなど)。

シェルがスクリプトまたはコマンドラインで渡されたコマンドを実行するとき、それは非対話型、非ログインシェルです。このようなシェルは常に実行されます。プログラムが別のプログラムを呼び出すと、シェルで小さなスクリプトを実際に実行して他のプログラムを呼び出すことは非常に一般的です。いくつかのシェルは、この場合、スタートアップファイルを読み込む(bashはで示されるファイルに実行BASH_ENV変数、zshの実行/etc/zshenv~/.zshenv)を、これは危険です:シェルはコンテキストのすべての種類に呼び出すことができます、あなたはそれがないかもしれない何かできることはほとんどありません何かを壊します。

少し簡略化しています。詳細についてはマニュアルを参照してください。


2
bash非対話型ログインシェルとして実行する方法の例を教えていただけますか?
ピョートルドブロゴスト

13
@PiotrDobrogostecho $- | bash -lx
ジル

1
これが一般的に正しいかどうかはわかりませんが、新しいターミナルを開くと(デフォルト設定を使用してosxで)、ユーザー名やパスワードを入力しなくてもログインシェルが表示されることに注意してください。
ケビンウィーラー

4
@KevinWheeler OSXでは、デフォルトで、ターミナルアプリケーションはログインシェルを実行します。(私が説明するように、シェルを開始するプログラムは、シェルがログインシェルとして機能するかどうかを決定します。)それは、物事を行う通常の方法ではありません。
ジル

2
@IAmJulianAcosta If FOOが環境変数(つまり、を.profile含むexport FOO=something)の場合、を含むすべてのサブプロセスで使用できますfoo.sh。あなたが変更した場合.profileexport FOO=something_else、その後./foo.sh、まだ印刷されますsomething、あなたが次にログインしたときまで。
ジル

48

ログインシェルにいるかどうかを確認するには:

prompt> echo $0
-bash # "-" is the first character. Therefore, this is a login shell.

prompt> echo $0
bash # "-" is NOT the first character. This is NOT a login shell.

Bashでは、以下も使用できますshopt login_shell

prompt> shopt login_shell
login_shell     off

(またはonログインシェル内)。

情報はman bash(呼び出しの検索)にあります。抜粋は次のとおりです。

ログインシェルは、引数ゼロの最初の文字が-であるシェル、または--loginオプションで開始されたシェルです。

これは自分でテストできます。SSHを使用するときはいつでも、ログインシェルを使用しています。例えば:

prompt> ssh user@localhost
user@localhost's password:
prompt> echo $0
-bash

ログインシェルを使用することの重要性は、すべての設定/home/user/.bash_profileが実行されることです。興味がある場合は、もう少し情報があります(からman bash

「bashが対話型ログインシェルとして、または--loginオプションを使用した非対話型シェルとして呼び出されると、最初に/ etc / profileファイルが存在する場合、そのファイルからコマンドを読み取って実行します。そのファイルを読み取った後、探し~/.bash_profile~/.bash_login、および~/.profile、そのためには、および読み込み、存在し、読み取り可能である。シェルはこの動作を抑制するために開始されたとき--noprofileオプションを使用することができる最初の1からのコマンドを実行します。」


23

ログインシェルで、argv[0][0] == '-'。これは、ログインシェルであることを認識する方法です。

そして状況によっては、「ログインシェル」ステータスに応じて動作が異なります。たとえば、ログインシェルではないシェルは、「ログアウト」コマンドを実行しません。


4
によればman bash「ログインシェルとは、引数ゼロの最初の文字が-であるもの、または--loginオプションで開始されるものです
ワイルドカード

18

GUIの新しいターミナルで起動されたシェルは、対話型の非ログインシェルになります。たとえば、.bashrcを取得しますが、.profileは取得しません。


4

ログインシェルタイプをチェックするTimothyの方法と組み合わせて、Gillesのすばらしい答えを詳しく説明します。

自分で物事を見たい場合は、以下のスニペットとシナリオを試してください。

シェルが(非)インタラクティブかどうかを確認する

if tty -s; then echo 'This is interactive shell.'; else echo 'This is non-interactive shell.'; fi

シェルが(非)ログインであるかどうかの確認

の出力がでecho $0始まる場合は-、ログインシェルです(echo $0出力例:)-bash。それ以外の場合は、非ログインシェルです(echo $0出力例:)bash

if echo $0 | grep -e ^\- 2>&1>/dev/null; then echo "This is login shell."; else echo "This is non-login shell."; fi;

上記の2つを組み合わせて、両方の情報を一度に取得しましょう。

THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; 
THIS_SHELL_LOGIN_TYPE='non-login'; 
if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; 
if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi;
echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"

シナリオ:

特別なオプションのない典型的なSSHセッション

ssh ubuntu@34.247.105.87
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1083-aws x86_64)

ubuntu@ip-172-31-0-70:~$ THIS_SHELL_INTERACTIVE_TYPE='non-interactive';
ubuntu@ip-172-31-0-70:~$ THIS_SHELL_LOGIN_TYPE='non-login';
ubuntu@ip-172-31-0-70:~$ if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi;
ubuntu@ip-172-31-0-70:~$ if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi;
ubuntu@ip-172-31-0-70:~$ echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"

interactive/login

スクリプトを実行するか、新しいシェルを介して明示的に実行する

ubuntu@ip-172-31-0-70:~$  bash -c 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; 
echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

interactive/non-login

ローカルスクリプトをリモートで実行する

ssh ubuntu@34.247.105.87 < checkmy.sh
Pseudo-terminal will not be allocated because stdin is not a terminal.
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1083-aws x86_64)

non-interactive/login

sshを介してリモートでコマンドを実行する

ssh ubuntu@34.247.105.87 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

non-interactive/non-login

-tスイッチを使用してリモートでssh経由でコマンドを実行する

-tスイッチを使用してsshを介してリモートでコマンドを実行する場合、明示的に対話型シェルを要求できます。

ssh ubuntu@34.247.105.87 -t 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

interactive/non-login

注:リモートでコマンドを実行するlogin shellことの詳細については、こちらのトピックをご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.