应用场景:

应用场景:

我了解交互式 shell 和非交互式 shell 之间的基本区别。但是登录 shell 和非登录 shell 到底有什么区别呢?

你能举例说明 a 的使用吗非登录交互壳?

答案1

登录 shell 是当您登录交互式会话时在您的用户 ID 下执行的第一个进程。登录过程告诉 shell 作为登录 shell,并遵循以下约定:传递参数 0,该参数通常是 shell 可执行文件的名称,并在-前面添加一个字符(例如-bash,通常是bash)。登录 shell 通常读取一个文件,该文件执行诸如设置环境变量之类的操作:/etc/profile对于~/.profile传统的 Bourne shell,~/.bash_profile另外还有 bash 、zsh 和csh 等。/etc/zprofile~/.zprofile/etc/csh.login~/.login

当您在文本控制台、通过 SSH 或使用 登录时su -,您会得到一个交互式登录壳。当您以图形模式登录时(在X 显示管理器),您不会获得登录 shell,而是获得会话管理器或窗口管理器。

运行一个是很少见的非交互式登录shell,但是当您使用显示管理器登录时,某些 X 设置会执行此操作,以便安排读取配置文件。其他设置(这取决于发行版和显示管理器)明确读取/etc/profile~/.profile不读取它们。获得非交互式登录 shell 的另一种方法是使用通过标准输入传递的命令远程登录,该命令不是终端,例如(与运行非交互式、非登录 shellssh example.com <my-script-which-is-stored-locally相反)。ssh example.com my-script-which-is-on-the-remote-machine

当您在现有会话的终端(屏幕、X 终端、Emacs 终端缓冲区、另一个 shell 等)中启动 shell 时,您会得到一个交互式、非登录壳。该 shell 可能会读取 shell 配置文件(~/.bashrc对于 bash 调用为bash/etc/zshrc对于~/.zshrczsh/etc/csh.cshrc~/.cshrccsh ,由 POSIX/XSI 兼容 shell 的变量指示的文件,ENV例如,当调用为 时sh$ENV如果设置并且~/.mkshrc对于 mksh 等)。

当 shell 运行脚本或在其命令行上传递的命令时,它是非交互、非登录壳。这样的 shell 一直在运行:很常见的是,当一个程序调用另一个程序时,它实际上在 shell 中运行一个小脚本来调用另一个程序。在这种情况下,某些 shell 会读取启动文件(bash 运行由变量指示的文件BASH_ENV,zsh 运行/etc/zshenv~/.zshenv),但这是有风险的:shell 可以在各种上下文中调用,并且几乎没有任何可能不可以做的事情。打破一些东西。

我稍微简化了一下,请参阅手册了解详细信息。

答案2

判断您是否处于登录 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(搜索调用)中找到。以下是摘录:

登录 shell 的参数零的第一个字符是 -,或者以 --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,并从第一个存在且可读的命令中读取并执行命令。 启动 shell 时可以使用 --noprofile 选项来禁止此行为。

答案3

我将详细阐述 Gilles 的精彩回答,并结合 Timothy 的检查登录 shell 类型的方法。

如果您想亲眼看看,请尝试下面的片段和场景。

检查 shell 是否是(非)交互式的

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

检查 shell 是否(非)登录

如果输出echo $0以 开头-,则它是登录 shell(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 会话

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

运行脚本或通过新 shell 显式执行

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使用switch通过 ssh 远程运行命令

当您想使用-tswitch 通过 ssh 远程运行命令时,可以显式请求交互式 shell。

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更多信息这里

答案4

在 GUI 中的新终端中启动的 shell 将是交互式非登录 shell。例如,它会获取您的 .bashrc,但不会获取您的 .profile。

相关内容