web-dev-qa-db-ja.com

ログインシェルと非ログインシェルの違いは何ですか?

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

非ログインインタラクティブシェルの使用例を教えていただけますか?

349
Igorio

ログインシェルは、インタラクティブセッションにログインしたときに、ユーザーIDで実行される最初のプロセスです。ログインプロセスは、通常はシェルの実行可能ファイルの名前である引数0を前に付加した-文字(例:-bashですが、通常はbashです)を使用して、ログインシェルとして動作するようにシェルに指示します。ログインシェルは通常、環境変数の設定などを行うファイル:従来のBourneシェルの場合は/etc/profileおよび~/.profile、bashの場合は~/.bash_profile/etc/zprofileおよび~/.zprofile(zshの場合)/etc/csh.loginおよび~/.login(cshなど).

テキストコンソール、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端末バッファー、別の内部のシェルなど)のターミナルでシェルを起動すると、インタラクティブな非ログインシェル。そのシェルは、シェル構成ファイル(zshのbash~/.bashrcおよび/etc/zshrcとして呼び出されたbshの場合は~/.zshrc、cshの場合は/etc/csh.cshrcおよび~/.cshrc、POSIX/XSI準拠のシェルの場合はENV変数で示されるファイル、およびdashなどのbashなどのbshを読み取る可能性があります。 sh、設定されている場合は$ENV、mkshの場合は~/.mkshrcなどとして呼び出されます。

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

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

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

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(Invocationを検索)にあります。以下は抜粋です。

ログインシェルは、引数ゼロの最初の文字が-であるシェル、または--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オプションは、シェルはこの動作を阻止するために開始されました。」

53
Timothy Pulliam

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

そして、場合によっては、「ログインシェル」のステータスによって動作が異なります。例えば。ログインシェルではないシェルは、「logout」コマンドを実行しません。

23
BOPOHOK

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

18
Julian

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

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

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

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 [email protected]
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 [email protected] < 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 [email protected] '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 [email protected] -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ではない理由についての詳細 ここ

5
Patrik Stas