6.3 交互式 shell(Interactive Shell)

6.3.1 什么是交互式 shell?(What is an Interactive Shell?)

交互式 shell 是一个在启动时不带有非选项参数(除非指定了“-s”选项),不带有“-c”选项的 shell,并且其输入、和报错输出都连接到终端(由 isatty(3)确定)的。或是由带有“-i”选项启动的 shell。

通常交互式 shell 是对用户终端进行读取和写入操作的。

当交互式 shell 启动时,“-s”选项可用于设置位置参数。

6.3.2 这是 shell 交互吗?(Is this Shell Interactive?)

在启动脚本中来确定 Bash 是不是运行于交互模式,只要测试一下特殊参数“-”的值就可以得出结果。当 shell 运行于交互模式时,该参数会包含字符“i”。例如:

case "$-" in
*i*) echo This shell is interactive ;;
*) echo This shell is not interactive ;;
esac

另外一种方式是在启动脚本中检查 PS1 变量;其不会设置于非交互式 shell 中,而只设置于交互模式。例如:

if [ -z "$PS1" ]; then
    echo This shell is not interactive
else
    echo This shell is interactive
fi

6.3.3 交互式 shell 的行为(Interactive Shell Behavior)

当 shell 运行于交互模式时,其会在某些方面改变其行为。

  1. 参见 6.2《Bash 启动文件》部分关于启动文件的读取与执行的描述。
  2. 默认开启作业控制(参见第 7 章《作业控制》)。当作业控制生效时,Bash 会忽略键盘产生的作业控制信号“SIGTTIN”、“SIGTTOU”和“SIGTSTP”。
  3. Bash 在读取命令的第一行之前先扩展并显示变量 PS1,并且在多行命令中读取第二行和后继行时先扩展并显示变量 PS2。Bash 在读取一个命令之后,但在该命令执行之前扩展并显示变量 PS0。关于提示符字符串转义序列的完整列表说明,可参见 6.9《控制提示符》。
  4. 在打印主提示符“$PS1”(参见 5.2《Bash 变量》)之前,Bash 会将数组变量 PORMPT_COMMANDS 设置的所有元素的值作为命令执行。
  5. 使用 Readline(参见第 8 章《命令行编辑》)从用户终端读取命令。
  6. 当 Bash 在读取一个命令时接收到一个 EOF 时,其会检查用“set -o”设置的“ignoreeof”的值来代替立即退出。
  7. 默认开启历史命令(参见 9.1《Bash 历史工具》)功能以及历史扩展(参见 9.3《历史交互》。当 shell 开启了历史功能,Bash 会在退出时将命令历史记录保存到由$HISTFILE 指定的文件中。
  8. 默认执行别名扩展(参见 6.6《别名》)。
  9. 在没有任何捕获器时,Bash 会忽略 SIGTERM 信号(参见 3.7.6《信号》)。
  10. 在没有任何捕获器时,会捕获并处理 SIGINT 信号。该信号可中断一些 shell 内建命令。
  11. 如果“huponexit”选项开启,则在一个交互式登录 shell 退出时会向所有的作业发送 SIGHUP 信号。
  12. 忽略“-n”调用选项,并且“set -n”不会有任何效果(参见 4.3.1《内建命令 set》)。
  13. Bash 会依据 shell 变量“MAIL”、“MAILPATH”和“MAILCHECK”对邮件进行周期性检查(参见 5.2《Bash 变量》)。
  14. 在设置了“set -u”之后,由引用未绑定变量所引起的扩展报错是不会使 shell 退出的(参见 3.5.3《Shell 参数扩展》)。
  15. 由于在表达式“${var:?word}”(参见 3.5.3《Shell 参数扩展》)中的 var 被释放或为空(null)所引起的表达式报错是不会使 shell 退出的。
  16. shell 内建命令出现的重定向报错是不会使 shell 退出的。
  17. 当运行于 POSIX 模式时,一个特殊的内建命令返回的错误状态是不会引起 shell 退出的(参见 6.11《Bash POSIX 模式》)。
  18. exec 命令的执行失败是不会引起 shell 退出的。(参见 4.1《Bourne Shell 内建命令》)
  19. 分析器的语法报错是不会引起 shell 退出。
  20. 对于内建命令 cd 的目录参数默认开启简单拼写纠错。(参见 4.3.2《内建命令 shopt》关于 shopt 内建命令的 cdspell 选项的描述)
  21. shell 如果检查 TMOUT 变量存在,在打印了提示符$PS1 之后,并在该变量指定的秒数之后没有读取到命令,则退出。