インタラクティブシェルと非インタラクティブシェルの基本的な違いを理解しています。しかし、ログインシェルと非ログインシェルを正確に区別するものは何ですか?
非ログインインタラクティブシェルの使用例を教えていただけますか?
ログインシェルは、インタラクティブセッションにログインしたときに、ユーザー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オプションは、シェルはこの動作を阻止するために開始されました。」
ログインシェルでは、argv[0][0] == '-'
。これは、ログインシェルであることを認識する方法です。
そして、場合によっては、「ログインシェル」のステータスによって動作が異なります。例えば。ログインシェルではないシェルは、「logout」コマンドを実行しません。
GUIの新しいターミナルで開始されたシェルは、対話型の非ログインシェルになります。たとえば、.bashrcはソースになりますが、.profileはソースになりません。
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 [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 [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
ではない理由についての詳細 ここ 。