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