我了解交互式外壳程序和非交互式外壳程序之间的基本区别。但是,将登录shell与非登录shell究竟有何区别呢?
您可以举非登录交互式外壳的使用示例吗?
我了解交互式外壳程序和非交互式外壳程序之间的基本区别。但是,将登录shell与非登录shell究竟有何区别呢?
您可以举非登录交互式外壳的使用示例吗?
Answers:
登录外壳程序是您登录交互式会话时在您的用户ID下执行的第一个过程。登录过程告诉shell遵循以下约定:传递参数0(通常是shell可执行文件的名称),并带有一个-
字符(例如-bash
,通常为)bash
。登录shell通常读取一个文件,该文件之类的设置环境变量:/etc/profile
和~/.profile
为传统Bourne shell的,~/.bash_profile
另外对于bash †,/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终端缓冲区,另一个终端中的外壳等)中启动外壳时,您将获得一个交互式非登录外壳。该外壳可能会读出壳配置文件(~/.bashrc
对于bash援引为bash
,/etc/zshrc
和~/.zshrc
用于zsh的,/etc/csh.cshrc
和~/.cshrc
用于CSH,该文件通过指定ENV
对POSIX / XSI兼容外壳,例如仪表板,KSH,和bash可变时作为调用sh
,$ENV
如果设置和~/.mkshrc
用于mksh等)。
当外壳程序运行脚本或通过其命令行传递的命令时,它是一个非交互式,非登录外壳程序。这样的shell一直在运行:当一个程序调用另一个程序时,它实际上在shell中运行一个很小的脚本来调用另一个程序是很常见的。在这种情况下,某些shell会读取启动文件(bash运行BASH_ENV
变量指示的文件,zsh运行/etc/zshenv
and ~/.zshenv
),但这是有风险的:可以在各种上下文中调用该shell,几乎没有什么可以做的打破一些东西。
†我正在简化一下,有关详细信息,请参阅手册。
bash
作为非交互式登录外壳运行?
echo $- | bash -lx
FOO
是环境变量(即.profile
包含export FOO=something
),则它可用于所有子流程,包括foo.sh
。如果更改.profile
到export FOO=something_else
,然后./foo.sh
将继续打印something
,直到下一次你登录。
告诉您是否在登录shell中:
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
在登录shell中)。
可以在man bash
(搜索调用)中找到信息。这是节选:
登录外壳是一个参数为零的第一个字符为-的外壳程序,或以--login选项开头的外壳程序。
您可以自己测试。每次使用SSH时,您都在使用登录Shell。例如:
prompt> ssh user@localhost
user@localhost's password:
prompt> echo $0
-bash
使用登录Shell的重要性在于/home/user/.bash_profile
将执行其中的所有设置。如果您有兴趣,可以从这里获得更多信息(来自man bash
)
“当bash作为交互式登录shell或具有--login选项的非交互式shell被调用时,它首先从文件/ etc / profile中读取并执行命令(如果该文件存在的话)。读取该文件后,它将查找
~/.bash_profile
,~/.bash_login
和~/.profile
以该顺序,并且读取和执行从存在并且是可读的。当外壳被启动以抑制这种行为可以使用的--noprofile选项的第一个命令“。
我将详细介绍Gilles的出色答案,并结合Timothy的方法来检查登录shell类型。
如果您想自己看看事物,请尝试以下片段和场景。
检查外壳是否(非)交互式
if tty -s; then echo 'This is interactive shell.'; else echo 'This is non-interactive shell.'; fi
检查外壳是否(非)登录
如果输出的echo $0
开头为-
,则为登录外壳程序(echo $0
输出示例:)-bash
。否则,它是非登录shell(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;
让我们将上面的两个结合在一起,一次获得两个信息:
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 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 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
Switch 通过SSH远程运行命令要使用ssh通过ssh远程运行命令时,可以显式请求交互式shell -t
。
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
更多信息。