「Bash」- 4 Solutions to Scenarios

Interactive Shell vs. Non-Interactive Shell

Bash Manual/6.3 Interactive Shells

Interactive Shell

针对 bash 命令,其语法格式为:bash [options] [command_string | file]

-s —— If the -s option is present, or if no arguments remain after option processing, then commands are read from the standard input. This option allows the positional parameters to be set when invoking an interactive shell or when reading input through a pipe.

-c —— If the -c option is present, then commands are read from the first non-option argument command_string. If there are arguments after the command_string, the first argument is assigned to $0 and any remaining arguments are assigned to the positional parameters. The assignment to $0 sets the name of the shell, which is used in warning and error messages.

  • is one started without non-option arguments (unless -s is specified) and without specifying the -c option, whose input and error output are both connected to terminals (as determined by isatty(3)),
  • or one started with the -i option. ⇒ -i —— If the -i option is present, the shell is interactive.

An interactive shell generally reads from and writes to a user’s terminal.

The -s invocation option may be used to set the positional parameters when an interactive shell is started.

如何判断当前是否为 Interactive Shell?
https://www.gnu.org/software/bash/manual/html_node/Is-this-Shell-Interactive_003f.html

交互式 Shell 所具备的行为:执行启动文件、作业控制、展开 PS0 PS1 PS2 等等变量、……
https://www.gnu.org/software/bash/manual/html_node/Interactive-Shell-Behavior.html

Login Shell vs. Non-Login Shell

https://www.gnu.org/software/bash/manual/html_node/Invoking-Bash.html#index-login-shell

A login shell is one whose first character of argument zero $0 is ‘-’, or one invoked with the –login option.

在 Login Shell 中,echo $0 ⇒ -bash # 注意开头的 ‘-’ 字符
在 Non-Login Shell 中,echo $0 ⇒ bash # 或是 /bin/bash,但总之开头没有‘-’字符

在某些情况下,

  • 在已经打开的终端里,想重新加载所有登录设置,则可以:bash –login 或 exec bash –login
  • 针对通过 SSH 执行单条命令的场景,如果希望该命令在完整的登录环境下运行,可以使用:ssh user@hostname -t ‘bash –login -c “your-command”‘

常用命令

shell script – What is the meaning of IFS=$’\n’ in bash scripting? – Unix & Linux Stack Exchange

使用 IFS 变量,指定循环的分隔符:

# 该脚本将输出:

读取输出,并定义变量:

指的是第一个命令行参数是`-‘,或者使用了–login 选项;

是一个没有非可选参数、没有-c 选项、其 stdin 和 stderr 都连接到终端(由 isatty(3)确定),或者由-i 选项启动的终端。如果 bash 是交互式的,会设置 PS1、$-包括 i,允许 shell 脚本或启动文件来测试此状态;

以下描述了 bash 如何执行其启动文件。如果任何文件存在但无法读取,bash 将报告错误。文件名中的波浪(~)在 EXPANSION 部分的 Tilde Expansion 下会描述;

当以 Login Shell 登录时,首先读取 /etc/profile(如果存在),然后在读取~/.bash_profile,~/.bash_login,~/.profile。按顺序、读取并执行文件中的命令。–noprofile 选项用于禁用这种行为;
Login Shell 退出时,如果存在的话~/.bash_logout 文件,则执行;

如果不是 Login Shell 而是 Interactive Shell,bash 读取 /etc/bash.bashrc,~/.bashrc,并执行其中的命令。使用–norc 选项,禁止这种行为。–rcfile file强制 bash 执行指定的文件,代替默认的 /etc/bash.bashrc,~/.bashrc;

当 bash 以非交互类的形式启动时(比如运行命令),它会查找环境变量中的 BASH_ENV 的值,并将其值视为要执行的文件。bash 的行为如下命令:

但是 PATH 环境变量的值,不会用于搜索文件;

如果使用 sh 调用 bash(比如执行 bash 的软连接,名为 sh),那么 bash 会尽量遵循 POSIX 标准,尽可能地模拟历史版本的 sh 的启动行为:

  • 当作为 Login Shell 或具有–login 选项的非交互式 shell 被调用时,它首先尝试以 /etc/profile 和~/.profile 的顺序读取和执行命令。–noprofile 选项可能用于抑制此行为;
  • 当以名称为 sh 的交互式 shell 调用时,bash 会查找变量 ENV,将其值作为要执行的文件。由于 shell 调用 sh 不会尝试从任何其他启动文件读取和执行命令,所以–rcfile 选项不起作用。使用名称 sh 调用的非交互式 shell 不会尝试读取任何其他启动文件。当作为 sh 调用时,bash 在读取启动文件后进入 posix 模式;

当 bash 以 posix 模式启动时,与–posix 命令行选项一样,它遵循 POSIX 标准。在此模式下,交互式 shell 读取 ENV 变量,将其值作为要执行的文件。不会执行其他的启动文件;

通过连接到网络连接的 stdin,bash 尝试来确定自己是如何被运行的,比如 rshd、sshd。如果 bash 确定是以这种方式运行的,它会从~/.bashrc 读取命令并执行(如果这些文件存在且可读)。如果调用 sh 就不会这样做。–norc 选项可能用于禁止此行为,而–rcfile 选项可能用于强制读取其他文件,但是 rshd 和 sshd 通常都不会使用这些选项来调用 shell 或允许指定它们;

真实用户组 ID 及有效用户组 ID
如果 shell 以有效用户(组)id 不等于真实用户(组)的 id 启动,并且没有提供-p 选项,则不会读取启动文件,shell 函数不会从环境继承,SHELLOPTS,BASHOPTS,CDPATH 和 GLOBIGNORE 变量(如果它们出现在环境中)将被忽略,有效用户 ID 会被设置为真实的用户 ID。如果在调用时提供-p 选项,启动行为是相同的,但是有效的用户 ID 不会被重置;