本文为 Bash Reference Manual 第5章:Shell Variables 的读书笔记。
完整的笔记目录参见Bash学习笔记总目录。
5.1 Bourne Shell Variables
Bash 使用某些 shell 变量的方式与 Bourne shell 相同。在某些情况下,Bash 会为变量分配默认值。
CDPATH 由冒号分隔的目录列表,用作 cd 内置命令的搜索路径。
默认为空值:
$ echo $CDPATH
$
HOME 当前用户的主目录;cd 内置命令的默认目录。该变量的值也用于波浪号扩展(见波浪号扩展)。
$ echo $HOME
/home/vagrant
$ cd /usr
$ cd
$ pwd
/home/vagrant
$ cd /usr
$ cd ~
$ pwd
/home/vagrant
IFS 一个分隔字段的字符列表;在 shell 扩展过程中用于拆分单词,并由 read 内置命令将行拆分为单词。有关单词拆分的描述,请参见单词拆分。
IFS的默认值是<space><tab><newline>。
$ echo "$IFS"|od -bc
0000000 040 011 012 012
\\t \\n \\n
0000004
$ read a1 b1 c1 <<< $'you are\\twelcome!'
$ echo $a1
you
$ echo $b1
are
$ echo $c1
welcome!
换行符在 IFS 中既是字段分隔符,也是行结束符。
## 默认行为
$ read a b c <<< $'you are\\nwelcome!'
$ echo $a
you
$
$ echo $b
are
$ echo $c
## 如果希望跨行读取
$ { read a b; read c; } <<< $'you are\\nwelcome!'
$ echo $a
you
$ echo $b
are
$ echo $c
welcome!
MAIL 如果值设置为文件名或目录名,并且未设置 MAILPATH 变量,Bash 会在指定文件或 Maildir 格式的目录中通知用户邮件到达。
MAILPATH 一个用冒号分隔的文件名列表,shell 会定期检查这些文件是否有新邮件。列表中的每个条目可以通过用‘?’将文件名与消息分开,来指定在邮件文件中有新邮件到达时打印的消息。在消息文本中使用 $_ 时,会扩展为当前邮件文件的名称。
OPTARG getopts 内建命令最近处理的选项参数的值。
OPTIND getopts 内建命令下一个要处理的参数的索引。
$ set — -H -L -P -D debug -O5
$ echo $OPTIND
1
$ getopts "HLPD:O:" name
$ echo "\\$? $?" "name: $name" "OPTIND: $OPTIND" "OPTARG: $OPTARG"
$? 0 name: H OPTIND: 2 OPTARG:
$ getopts "HLPD:O:" name
$ echo "\\$? $?" "name: $name" "OPTIND: $OPTIND" "OPTARG: $OPTARG"
$? 0 name: L OPTIND: 3 OPTARG:
$ getopts "HLPD:O:" name
$ echo "\\$? $?" "name: $name" "OPTIND: $OPTIND" "OPTARG: $OPTARG"
$? 0 name: P OPTIND: 4 OPTARG:
$ getopts "HLPD:O:" name
$ echo "\\$? $?" "name: $name" "OPTIND: $OPTIND" "OPTARG: $OPTARG"
$? 0 name: D OPTIND: 6 OPTARG: debug
$ getopts "HLPD:O:" name
$ echo "\\$? $?" "name: $name" "OPTIND: $OPTIND" "OPTARG: $OPTARG"
$? 0 name: O OPTIND: 7 OPTARG: 5
$ getopts "HLPD:O:" name
$ echo "\\$? $?" "name: $name" "OPTIND: $OPTIND" "OPTARG: $OPTARG"
$? 1 name: ? OPTIND: 7 OPTARG:
PATH 一个以冒号分隔的目录列表,shell 会在这些目录中查找命令。在 PATH 值中,零长度(空)目录名表示当前目录。空目录名可以表现为两个相邻的冒号,或者作为开头或结尾的冒号。默认路径依赖于系统,由安装 bash 的管理员设置。常见的值是“/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin”。
PS1 主提示符字符串。默认值是‘s-v$ ’。有关在显示 PS1 前会展开的完整转义序列列表,请参阅控制提示符。
[vagrant@ol9-vagrant ~]$ echo $PS1
[\\u@\\h \\W]\\$
PS2 次级提示符字符串。默认值是‘> ’。PS2 展开方式与 PS1 在显示前的方式相同。
当需要更多输入以完成命令时,使用辅助提示 PS2
$ for i in 1 2 3; do
> echo $i
> done
1
2
3
5.2 Bash Variables
这些变量由 Bash 设置或使用,但其他 Shell 通常不会特别处理它们。
在不同章节中描述了 Bash 使用的一些变量:用于控制作业控制功能的变量(参见作业控制变量)。
_
($_,一个下划线)。根据上下文,这有多种含义。在 shell 启动时,$_被设置为用于调用 shell 或正在执行的 shell 脚本的路径名,该路径名通过环境变量或参数列表传入。随后,它会扩展为前一个在前台执行的简单命令的最后一个参数(展开后)。它还会被设置为用于调用每个执行命令的完整路径名,并放入导出到该命令的环境中。检查邮件时,$_会扩展为邮件文件的名称。
Using username "vagrant".
Authenticating with public key "vagrant"
Welcome to Oracle Linux Server release 9.5 (GNU/Linux 5.15.0-206.153.7.el8uek.x86_64)
The Oracle Linux End-User License Agreement can be viewed here:
* /usr/share/eula/eula.en_US
For additional packages, updates, documentation and community help, see:
* https://yum.oracle.com/
Last login: Mon Jan 12 02:29:36 2026 from 10.0.2.2
[vagrant@ol9-vagrant ~]$ echo $_
/home/vagrant/.bashrc
[vagrant@ol9-vagrant ~]$ set — 1 2 3
[vagrant@ol9-vagrant ~]$ echo $_
3
💡 $_作为最后一个参数是最常用的用法。
BASH 用于执行当前 Bash 实例的完整路径名。
$ echo $BASH
/bin/bash
$ ls -l /bin
lrwxrwxrwx. 1 root root 7 Oct 26 2024 /bin –> usr/bin
$ ls -l /usr/bin/bash
-rwxr-xr-x. 1 root root 1389064 May 1 2024 /usr/bin/bash
BASHOPTS 一个以冒号分隔的已启用 shell 选项的列表。列表中的每个单词都是 shopt 内置命令的 -s 选项的有效参数(参见 Shopt 内置命令)。BASHOPTS 中出现的选项是由 ‘shopt’ 报告为“开启”的选项。如果在 Bash 启动时该变量存在于环境中,shell 会在读取任何启动文件之前启用列表中的每个选项。如果该变量被导出,子 shell 将启用列表中的每个选项。此变量为只读。 用于执行当前 Bash 实例的完整路径名。
$ echo $BASHOPTS
checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
$ IFS=':'; for opt in $BASHOPTS; do shopt $opt; done
checkwinsize on
cmdhist on
complete_fullquote on
expand_aliases on
extquote on
force_fignore on
globasciiranges on
histappend on
hostcomplete on
interactive_comments on
login_shell on
progcomp on
promptvars on
sourcepath on
BASHPID 扩展为当前 Bash 进程的进程 ID。在某些情况下,这与 $$ 不同,例如不需要重新初始化 Bash 的子 shell。对 BASHPID 的赋值没有效果。如果 BASHPID 被取消设置,它将失去特殊属性,即使随后重新设置也一样。
$ echo "BASHPID: $BASHPID" "\\$\\$: $$"
BASHPID: 14709 $$: 14709
$ ( echo "BASHPID: $BASHPID" "\\$\\$: $$" )
BASHPID: 14968 $$: 14709
BASH_ALIASES 一个关联数组变量,其成员对应于由 alias 内建命令维护的内部别名列表。(参见 Bourne Shell 内建命令)。添加到该数组的元素会出现在别名列表中;然而,目前取消设置数组元素不会导致别名从别名列表中移除。如果 BASH_ALIASES 被取消设置,它将失去其特殊属性,即使之后重新设置也是如此。
$ for ali in ${BASH_ALIASES[@]}; do
> echo $ali
> done
zgrep –color=auto
xzgrep –color=auto
zfgrep –color=auto
egrep –color=auto
grep –color=auto
fgrep –color=auto
ls -l –color=auto
ls -d .* –color=auto
xzegrep –color=auto
zegrep –color=auto
ls –color=auto
xzfgrep –color=auto
BASH_ARGC 一个数组变量,其值是当前 Bash 执行调用堆栈中每个帧的参数数量。当前子程序(使用 . 或 source 执行的 shell 函数或脚本)的参数数量位于堆栈顶部。当执行子程序时,传递的参数数量会被推入 BASH_ARGC。只有在扩展调试模式下(参见 shopt 内建命令的 extdebug 选项说明)Shell 才会设置 BASH_ARGC。在 Shell 已开始执行子程序后设置 extdebug,或者在未设置 extdebug 时引用该变量,可能会导致值不一致。对 BASH_ARGC 的赋值无效,也不能取消设置。
BASH_ARGV 一个数组变量,包含当前 Bash 执行调用堆栈中的所有参数。最后一个子例程调用的最后一个参数位于堆栈顶部;初始调用的第一个参数位于堆栈底部。当执行子例程时,Shell 会将提供的参数压入 BASH_ARGV。只有在扩展调试模式下,Shell 才会设置 BASH_ARGV(请参阅 Shopt 内建命令的 extdebug 选项描述)。在 Shell 开始执行脚本之后设置 extdebug,或者在未设置 extdebug 时引用此变量,可能会导致值不一致。对 BASH_ARGV 的赋值无效,且无法取消设置。
$ cat ./argc_argv_demo.sh
#!/bin/bash
shopt -s extdebug
func1() {
echo "=== func1 is called ==="
echo "func1 arg count: $#"
echo "func1 arg list: $@"
echo "BASH_ARGC: ${BASH_ARGC[@]}"
echo "BASH_ARGV: ${BASH_ARGV[@]}"
echo "call stack depth: ${#BASH_ARGC[@]}"
local depth=${#BASH_ARGC[@]}
local arg_count=${BASH_ARGC[depth-1]}
echo "arg count (from BASH_ARGC): $arg_count"
func2 "inner1" "inner2"
}
func2() {
echo ""
echo "=== func2 is called ==="
echo "func2 arg count: $#"
echo "func2 arg list: $@"
echo "BASH_ARGC: ${BASH_ARGC[@]}"
echo "BASH_ARGV: ${BASH_ARGV[@]}"
echo "call stack depth: ${#BASH_ARGC[@]}"
show_current_args
}
show_current_args() {
local total_args=0
local i j
echo ""
echo "=== parse call stack ==="
# BASH_ARGV is reverse stored (from the last parameter)
for ((i=0; i<${#BASH_ARGC[@]}; i++)); do
local arg_count=${BASH_ARGC[i]}
echo "stack $i has $arg_count parameters:"
for ((j=0; j<arg_count; j++)); do
local index=$((total_args + j))
echo " param $((j+1)): ${BASH_ARGV[index]}"
done
((total_args += arg_count))
done
}
# main
echo "Initial BASH_ARGC: ${BASH_ARGC[@]}"
echo "Initial BASH_ARGV: ${BASH_ARGV[@]}"
echo ""
func1 "arg1" "arg2" "arg3"
$ ./argc_argv_demo.sh
Initial BASH_ARGC: 0
Initial BASH_ARGV:
=== func1 is called ===
func1 arg count: 3
func1 arg list: arg1 arg2 arg3
BASH_ARGC: 3 0
BASH_ARGV: arg3 arg2 arg1
call stack depth: 2
arg count (from BASH_ARGC): 0
=== func2 is called ===
func2 arg count: 2
func2 arg list: inner1 inner2
BASH_ARGC: 2 3 0
BASH_ARGV: inner2 inner1 arg3 arg2 arg1
call stack depth: 3
=== parse call stack ===
stack 0 has 0 parameters:
stack 1 has 2 parameters:
param 1: inner2
param 2: inner1
stack 2 has 3 parameters:
param 1: arg3
param 2: arg2
param 3: arg1
stack 3 has 0 parameters:
BASH_ARGV0 当引用时,该变量会扩展为 shell 或 shell 脚本的名称(与 $0 相同;参见特殊参数,了解特殊参数 0 的描述)。给 BASH_ARGV0 赋值会将 $0 设置为相同的值。如果 BASH_ARGV0 被取消设置,它将失去特殊属性,即使之后重新设置也是如此。
$ echo $BASH_ARGV0
-bash
$ echo $0
-bash
BASH_CMDS 一个关联数组变量,其成员对应于由 hash 内置命令维护的命令内部哈希表(参见 Bourne Shell 内置命令)。向该数组添加元素会使它们出现在哈希表中;然而,当前取消设置数组元素并不会从哈希表中移除命令名。如果 BASH_CMDS 被取消设置,它将失去其特殊属性,即使之后重新设置也不例外。
$ hash
hits command
7 /usr/bin/vi
2 /usr/bin/file
1 /usr/bin/find
2 /usr/bin/env
1 /usr/bin/chmod
21 /usr/bin/ls
1 /usr/bin/cat
10 /usr/bin/rm
$ echo ${BASH_CMDS[@]}
/usr/bin/vi /usr/bin/file /usr/bin/find /usr/bin/env /usr/bin/chmod /usr/bin/ls /usr/bin/cat /usr/bin/rm
**BASH_COMMAND ** 展开为当前正在执行或即将执行的命令,除非 shell 正在执行一个由 trap 触发的命令,在这种情况下,它表示 trap 触发时正在执行的命令。如果 BASH_COMMAND 未设置,它将失去特殊属性,即使随后重新设置也一样。
$ echo "current command: $BASH_COMMAND"
current command: echo "current command: $BASH_COMMAND"
BASH_COMPAT 该值用于设置 Shell 的兼容性级别。有关各种兼容性级别及其效果的描述,请参见 Shell 兼容模式。该值可以是小数(例如 4.2)或整数(例如 42),对应所需的兼容性级别。如果未设置 BASH_COMPAT 或将其设置为空字符串,则兼容性级别将设置为当前版本的默认值。如果 BASH_COMPAT 设置为无效的兼容性级别值,Shell 将显示错误信息,并将兼容性级别设置为当前版本的默认值。部分有效值对应于下文描述的兼容性级别(参见 Shell 兼容模式)。例如,4.2 和 42 是有效值,对应 compat42 shopt 选项,并将兼容性级别设置为 42。当前版本也是一个有效值。
$ echo $BASH_COMPAT
$
$ shopt |grep compat
compat31 off
compat32 off
compat40 off
compat41 off
compat42 off
compat43 off
compat44 off
BASH_ENV 如果在调用 Bash 执行 shell 脚本时设置了此变量,其值将被展开并用作在执行脚本前读取的启动文件的名称。Bash 不会使用 PATH 来搜索生成的文件名。参见 Bash 启动文件。
BASH_EXECUTION_STRING -c 调用选项的命令参数。
$ bash -c 'echo "The command executing is: $BASH_EXECUTION_STRING"'
The command executing is: echo "The command executing is: $BASH_EXECUTION_STRING"
BASH_LINENO 一个数组变量,其成员是源文件中每个对应的 FUNCNAME 成员被调用的行号。${BASH_LINENO[$i]} 是 ${FUNCNAME[$i]} 被调用的源文件 (${BASH_SOURCE[$i 1]}) 中的行号(如果在另一个 shell 函数中引用,则为 ${BASH_LINENO[$i-1]})。使用 LINENO 获取当前行号。对 BASH_LINENO 的赋值没有效果,也不能取消设置。
$ cat -n ./bash_lineno_demo.sh
1 #!/bin/bash
2
3 func1() {
4 echo "=== func1 is called ==="
5 echo "FUNCNAME: ${FUNCNAME[@]}"
6 echo "BASH_LINENO: ${BASH_LINENO[@]}"
7 echo "BASH_SOURCE: ${BASH_SOURCE[@]}"
8 echo "LINENO: $LINENO"
9
10 func2
11 }
12
13 func2() {
14 echo "=== func2 is called ==="
15 echo "FUNCNAME: ${FUNCNAME[@]}"
16 echo "BASH_LINENO: ${BASH_LINENO[@]}"
17 echo "BASH_SOURCE: ${BASH_SOURCE[@]}"
18 echo "LINENO: $LINENO"
19
20 }
21
22 echo "=== main is called ==="
23 echo "FUNCNAME: ${FUNCNAME[@]}"
24 echo "BASH_LINENO: ${BASH_LINENO[@]}"
25 echo "BASH_SOURCE: ${BASH_SOURCE[@]}"
26 echo "LINENO: $LINENO"
27
28 func1
$ ./bash_lineno_demo.sh
=== main is called ===
FUNCNAME:
BASH_LINENO: 0
BASH_SOURCE: ./bash_lineno_demo.sh
LINENO: 26
=== func1 is called ===
FUNCNAME: func1 main
BASH_LINENO: 28 0
BASH_SOURCE: ./bash_lineno_demo.sh ./bash_lineno_demo.sh
LINENO: 8
=== func2 is called ===
FUNCNAME: func2 func1 main
BASH_LINENO: 10 28 0
BASH_SOURCE: ./bash_lineno_demo.sh ./bash_lineno_demo.sh ./bash_lineno_demo.sh
LINENO: 18
BASH_LOADABLES_PATH 用冒号分隔的目录列表,enable 命令将在这些目录中查找可动态加载的内置命令。
BASH_MONOSECONDS 每次引用此变量时,它都会扩展为系统单调时钟返回的值(如果有的话)。如果没有单调时钟,则相当于 EPOCHSECONDS。如果 BASH_MONOSECONDS 未设置,它将失去特殊属性,即使随后重新设置也是如此。
BASH_REMATCH 一个数组变量,其成员由‘=~’二元运算符赋值给[[ 条件命令(参见条件构造)。索引为0的元素是与整个正则表达式匹配的字符串部分。索引为n的元素是与第n个括号子表达式匹配的字符串部分。
## GNU bash, version 5.1.8(1)-release (x86_64-redhat-linux-gnu)
$ [[ $(bash –version | head -1) =~ version\\ ([0-9]+)\\.([0-9]+)\\.([0-9]+) ]]
$ echo ${#BASH_REMATCH[@]}
4
$ for match in ${BASH_REMATCH[@]}; do
echo $match
done
version 5.1.8
5
1
8
BASH_SOURCE 一个数组变量,其成员是FUNCNAME数组变量中相应shell函数名称定义所在的源文件名。shell函数${FUNCNAME[$i]}定义在文件${BASH_SOURCE[$i]}中,并从${BASH_SOURCE[$i-1]}调用。对BASH_SOURCE的赋值没有效力,也不能取消设置它。
示例参见BASH_LINENO。
BASH_SUBSHELL 在每个子shell或子shell环境中,当shell开始在该环境中执行时,值会增加1。初始值为0。如果BASH_SUBSHELL被取消设置,它将失去特殊属性,即使随后重新设置也不例外。
$ echo $BASH_SUBSHELL
0
$ ( echo $BASH_SUBSHELL )
1
$ ( echo $BASH_SUBSHELL; (echo $BASH_SUBSHELL) )
1
2
BASH_TRAPSIG 设置为在执行陷阱动作时对应的信号编号。有关信号编号和陷阱执行的信息,请参见 trap 的描述(参见 Bourne Shell 内置命令)。
💡 为何打印不出来
BASH_VERSINFO 一个只读数组变量(参见数组),其成员保存此 Bash 实例的版本信息。数组成员分配的值如下:
BASH_VERSINFO[0] 主版本号(发布号)。
BASH_VERSINFO[1] 次版本号(版本号)。
BASH_VERSINFO[2] 补丁级别。
BASH_VERSINFO[3] 构建版本。
BASH_VERSINFO[4] 发布状态(例如,测试版)。
BASH_VERSINFO[5] MACHTYPE 的值。
$ echo ${#BASH_VERSINFO[@]}
6
$ echo ${BASH_VERSINFO[@]}
5 1 8 1 release x86_64-redhat-linux-gnu
BASH_VERSION
展开为描述此 Bash 实例版本的字符串(例如,5.2.37(3)-release)。
$ echo $BASH_VERSION
5.1.8(1)-release
$ bash –version
GNU bash, version 5.3.0(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2025 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ bash
$ echo $BASH_VERSION
5.3.0(1)-release
💡 BASH_VERSION才是当前运行bash实例的版本,而bash –version是某bash二进制程序的版本。
BASH_XTRACEFD 如果设置为对应于有效文件描述符的整数,当启用“set -x”时,Bash 会将生成的跟踪输出写入该文件描述符,而不是标准错误。这允许跟踪输出与诊断和错误消息分开。当 BASH_XTRACEFD 被取消设置或赋予新值时,文件描述符会被关闭。取消设置 BASH_XTRACEFD 或将其赋为空字符串会导致跟踪输出发送到标准错误。请注意,将 BASH_XTRACEFD 设置为 2(标准错误文件描述符)然后取消设置,会导致标准错误被关闭。
$ set -x
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant '~/test'
$ pwd
+ pwd
/home/vagrant/test
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant '~/test'
$ rm abc
+ rm abc
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant '~/test'
$ exec 4>trace.log
+ exec
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant '~/test'
$ BASH_XTRACEFD=4
+ BASH_XTRACEFD=4
$ pwd
/home/vagrant/test
$ rm abc
rm: cannot remove 'abc': No such file or directory
$ ls /dev/fd
0 1 2 3 4
$ unset BASH_XTRACEFD
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant '~/test'
$ ls /dev/fd
+ ls –color=auto /dev/fd
0 1 2 3
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant '~/test'
$ set +x
+ set +x
$ cat trace.log
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant '~/test'
+ pwd
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant '~/test'
+ rm abc
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant '~/test'
+ ls –color=auto /dev/fd
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant '~/test'
+ unset BASH_XTRACEFD
CHILD_MAX 设置 shell 记住的已退出子进程状态值的数量。Bash 不允许将此值降低到 POSIX 规定的最小值以下,并且存在一个最大值(当前为 8192),不得超过。最小值取决于系统。
COLUMNS 用于 select 命令在打印选择列表时确定终端宽度。如果启用了 checkwinsize 选项(参见 The Shopt Builtin),或者在交互式 shell 中收到 SIGWINCH 信号时,会自动设置。
$ shopt checkwinsize
checkwinsize on
$ echo $LINES $COLUMNS
35 111
## 最大化终端窗口
$ echo $LINES $COLUMNS
53 172
COMP_CWORD 指向包含当前光标位置的单词在 ${COMP_WORDS} 中的索引。该变量仅在由可编程补全功能调用的 shell 函数中可用(参见 可编程补全)。
COMP_KEY 用于调用当前补全函数的键(或键序列的最后一个键)。此变量仅在由可编程补全功能调用的 shell 函数和外部命令中可用(参见可编程补全)。
COMP_LINE 当前命令行。此变量仅在由可编程补全功能调用的 shell 函数和外部命令中可用(参见可编程补全)。
COMP_POINT 当前光标位置相对于当前命令开头的索引。如果当前光标位置在当前命令的末尾,则该变量的值等于 ${#COMP_LINE}。此变量仅在由可编程补全功能调用的 shell 函数和外部命令中可用(参见可编程补全)。
COMP_TYPE 设置为对应尝试补全类型的整数值,该类型会导致调用补全函数:TAB 表示正常补全,‘?’ 表示连续按 Tab 键列出补全选项,‘!’ 表示在部分单词补全时列出替代选项,‘@’ 表示列出修改过的单词的补全选项,或 ‘%’ 表示菜单补全。此变量仅在由可编程补全功能调用的 shell 函数和外部命令中可用(参见可编程补全)。
COMP_WORDBREAKS Readline 库在执行单词补全时视为单词分隔符的字符集合。如果未设置 COMP_WORDBREAKS,则其特殊属性将丢失,即使随后重新设置也是如此。
COMP_WORDS 由当前命令行的各个单词组成的数组变量。命令行按 Readline 的方式拆分为单词,使用前述的 COMP_WORDBREAKS。此变量仅在由可编程补全功能调用的 shell 函数中可用(参见可编程补全)。
COMPREPLY 一个数组变量,Bash 从中读取由可编程补全功能调用的 shell 函数生成的可能补全。每个数组元素包含一个可能的补全。
COPROC 一个数组变量,用于保存未命名协程的输出和输入文件描述符(参见协程)。
$ coproc { bc -l; }
[1] 15778
$ echo ${COPROC[@]}
63 60
$ echo ${#COPROC[@]}
2
$ echo "1+2" >&60
$ read -u63 result
$ echo $result
3
$ echo "quit" >&60
$
[1]+ Done coproc COPROC { bc -l; }
DIRSTACK 一个包含当前目录栈内容的数组变量。目录在栈中出现的顺序与 dirs 内置命令显示的顺序相同。给这个数组变量的成员赋值可以用来修改已在栈中的目录,但必须使用 pushd 和 popd 内置命令来添加和移除目录。对该变量赋值不会改变当前目录。如果 DIRSTACK 未设置,它将失去其特殊属性,即使随后重新设置也一样。
$ dirs -c
$ dirs -l
/home/vagrant/test
$ echo ${#DIRSTACK[@]}
1
$ echo ${DIRSTACK[@]}
/home/vagrant/test
$ pushd /usr/include
/usr/include ~/test
$ echo ${DIRSTACK[@]}
/usr/include /home/vagrant/test
$ echo ${#DIRSTACK[@]}
2
EMACS 如果 Bash 在启动 shell 时在环境中找到这个变量,并且其值为 ‘t’,那么 Bash 会认为 shell 正在 Emacs 的 shell 缓冲区中运行,并禁用行编辑。
ENV 在以 POSIX 模式调用交互式 shell 时,它会像 BASH_ENV(参见 Bash 启动文件)一样进行展开和执行。
EPOCHREALTIME 每次引用此参数时,它会展开为自 Unix 纪元以来的秒数,以微秒精度的浮点值表示(有关纪元的定义,请参见 C 库函数 time 的文档)。对 EPOCHREALTIME 的赋值将被忽略。如果 EPOCHREALTIME 未设置,则会失去其特殊属性,即使随后重新设置也是如此。
💡 Unix 纪元(EPOCH)是指 1970年1月1日 00:00:00 UTC(协调世界时)。1969年Ken Thompson 开始开发 Unix,从节省内存和避免处理太早的日期考虑,因此选择了这个日期。
$ echo $EPOCHREALTIME
1768203099.663270
$ date –date=@0
Thu Jan 1 12:00:00 AM UTC 1970
$ date –date=@$EPOCHREALTIME
Mon Jan 12 07:32:00 AM UTC 2026
EPOCHSECONDS 每次引用此参数时,它都会扩展为自 Unix 纪元以来的秒数(有关纪元的定义,请参阅 C 库函数 time 的文档)。对 EPOCHSECONDS 的赋值将被忽略。如果 EPOCHSECONDS 未设置,它将失去其特殊属性,即使随后重新设置也不例外。
💡 EPOCHSECONDS 是整数,EPOCHREALTIME是小数。
$ echo $EPOCHSECONDS $EPOCHREALTIME
1768203564 1768203564.474086
$ date –date=@1768203564
Mon Jan 12 07:39:24 AM UTC 2026
$ date –date=@'1768203564.474086'
Mon Jan 12 07:39:24 AM UTC 2026
EUID 当前用户的数字有效用户ID。此变量为只读。
$ echo $EUID
1000
$ id -u
1000
EXECIGNORE 一个用冒号分隔的 shell 模式列表(参见模式匹配),定义在使用 PATH 进行命令搜索时应被忽略的文件名集合。其完整路径名与这些模式之一匹配的文件,在通过 PATH 查找进行自动补全和命令执行时不被视为可执行文件。这不会影响 [、test 和 [[ 命令的行为。命令哈希表中的完整路径名不受 EXECIGNORE 的影响。使用此变量可忽略设置了可执行位但并非真正可执行的共享库文件。模式匹配会遵循 extglob shell 选项的设置。
FCEDIT fc 内置命令使用的默认编辑器。
$ echo $FCEDIT
FIGNORE 在执行文件名补全时要忽略的以冒号分隔的后缀列表。文件名的后缀如果与 FIGNORE 中的某个条目匹配,则该文件名将从匹配的文件名列表中排除。一个示例值是“.o:~”
FUNCNAME 一个数组变量,包含当前执行调用栈中所有 shell 函数的名称。索引为 0 的元素是任何当前正在执行的 shell 函数的名称。最底层的元素(索引最高的那个)是 “main”。只有在 shell 函数正在执行时该变量才存在。对 FUNCNAME 的赋值不会产生任何效果。如果取消设置 FUNCNAME,它将失去其特殊属性,即使随后重新设置也不例外。
该变量可以与 BASH_LINENO 和 BASH_SOURCE 一起使用。FUNCNAME 的每个元素在 BASH_LINENO 和 BASH_SOURCE 中都有对应的元素来描述调用栈。例如,${FUNCNAME[$i]} 是从文件 ${BASH_SOURCE[$i 1]} 的第 ${BASH_LINENO[$i]} 行调用的。builtin 命令 caller 使用这些信息显示当前调用栈。
示例见BASH_LINENO。
FUNCNEST 大于 0 的数值定义了最大的函数嵌套层级。超过此嵌套层级的函数调用会导致当前命令中止。
GLOBIGNORE 由冒号分隔的模式列表,定义在文件名扩展时要忽略的文件名集合。如果由文件名扩展模式匹配的文件名也匹配 GLOBIGNORE 中的某个模式,它将从匹配列表中移除。模式匹配会遵循 extglob shell 选项的设置。
GLOBSORT 控制文件名扩展结果的排序方式。该变量的值指定文件名扩展结果的排序标准和排序顺序。如果该变量未设置或设置为空字符串,文件名扩展将使用按名称排序的历史行为,按 LC_COLLATE shell 变量确定的升序字典顺序排序。
如果设置了,有效值以可选的‘+’开头(会被忽略),或以‘-’开头(将排序顺序从升序改为降序),后面跟排序说明符。有效的排序说明符有‘name’、‘numeric’、‘size’、‘mtime’、‘atime’、‘ctime’和‘blocks’,分别按文件名、以数字而非字典顺序排序的名字、文件大小、修改时间、访问时间、inode更改时间和块数对文件进行排序。如果任何非名称键比较结果相等(例如,如果两个文件大小相同),排序将使用名称作为次要排序键。
例如,值为-mtime会按修改时间降序(最新的排在最前面)对结果进行排序。
“numeric”(数字)说明符将仅由数字组成的名称视为数字,并按其数值进行排序(例如,“2”会排在“10”之前)。当使用“numeric”时,包含非数字的名称会排在所有全数字名称之后,并按名称使用传统方式进行排序。
“nosort”排序说明符会完全禁用排序;Bash 会按照从文件系统读取的顺序返回结果,忽略任何前导的“-”。
如果缺少排序说明符,则默认为按名称排序,因此值为“+”等同于空字符串,值为“-”则按名称降序排序。
任何无效的值都会恢复历史的排序行为。
$ for i in 1 2 3 4; do
filename=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 4 | head -n 1)
> $filename
done
$ ls
JmSZ JNXQ sBoU wUwy
$ echo *
JmSZ JNXQ sBoU wUwy
## sort by creat time, same as the output of ls command
$ GLOBSORT=ctime echo *
JmSZ JNXQ sBoU wUwy
GROUPS 一个数组变量,包含当前用户所属于的组列表。对 GROUPS 的赋值没有效果。如果取消设置 GROUPS,它将失去其特殊属性,即使随后重新设置也不例外。
$ groups
vagrant wheel
$ echo ${#GROUPS[@]}
2
$ echo ${GROUPS[@]}
1000 10
$ sudo groupadd grp1
$ sudo groupadd grp2
$ sudo usermod -aG grp1,grp2 $USER
$ echo ${GROUPS[@]}
1000 10
$ orguser=$USER; sudo su – $orguser
$ echo ${#GROUPS[@]}
4
$ echo ${GROUPS[@]}
1000 10 1001 1002
$ sudo gpasswd -d $USER grp1
Removing user vagrant from group grp1
$ sudo gpasswd -d $USER grp2
Removing user vagrant from group grp2
$ sudo groupdel grp1
$ sudo groupdel grp2
histchars 控制历史扩展、快速替换和标记化的两个或三个字符(参见历史扩展)。第一个字符是历史扩展字符,用于开始历史扩展,通常是 ‘!’. 第二个字符是快速替换字符,通常是 ‘^’. 当它出现在行首时,历史替换会重复前一个命令,将一个字符串替换为另一个字符串。可选的第三个字符是历史注释字符,通常是 ‘#’,当它作为单词的第一个字符出现时,表示该行剩余部分为注释。历史注释字符会禁用该行剩余单词的历史替换,它不一定会导致 shell 解析器将行的其余部分视为注释。
HISTCMD 当前命令的历史编号或历史列表中的索引。对 HISTCMD 的赋值没有效果。如果 HISTCMD 未设置,它将失去其特殊属性,即使随后重新设置也一样。
$ echo $HISTCMD
1013
$ fc -l
998 echo ${GROUPS[@]}
999 export PS1='$ '
...
1013 echo $HISTCMD
HISTCONTROL 一个由冒号分隔的值列表,用于控制命令如何保存到历史列表中。如果值列表中包含“ignorespace”,则以空格字符开头的行不会被保存到历史列表中。值为“ignoredups”会导致与前一个历史条目匹配的行不被保存。值为“ignoreboth”是“ignorespace”和“ignoredups”的简写。值为“erasedups”会在当前行保存之前,删除历史列表中所有与当前行匹配的前置行。以上列表中未包含的任何值都会被忽略。如果未设置HISTCONTROL,或者未包含有效值,Bash 会将 shell 解析器读取的所有行保存到历史列表中,但需遵守HISTIGNORE的值。如果多行复合命令的第一行已保存,则第二行及后续行不进行测试,并且无论HISTCONTROL的值如何都将添加到历史记录中。如果第一行未保存,则该命令的第二行及后续行也不会被保存。
$ echo $HISTCONTROL
ignoredups
HISTFILE 保存命令历史记录的文件名。Bash 默认将其设置为 ~/.bash_history。如果 HISTFILE 未设置或为空,Shell 在退出时不会保存命令历史记录。
$ echo $HISTFILE
/home/vagrant/.bash_history
HISTFILESIZE 历史文件中包含的最大行数。当为该变量赋值时,如果需要,历史文件会被截断,以确保包含的历史条目总行数不超过该值,截断方式是移除最早的条目。如果历史列表包含多行条目,为了避免留下不完整的历史条目,历史文件的行数可能会超过该最大值。Shell退出时或通过 history 内置命令写入历史文件后,历史文件也会被截断到此大小。如果值为 0,历史文件将被截断为零大小。非数字值以及小于零的数字值会阻止截断。Shell在读取任何启动文件后,将默认值设置为 HISTSIZE 的值。
$ echo $HISTFILESIZE
1000
HISTIGNORE 一个以冒号分隔的模式列表,用于决定哪些命令行应保存到历史记录列表中。如果命令行与HISTIGNORE的值中的某个模式匹配,则该命令行不会被保存到历史记录列表中。每个模式都从行首开始锚定,并且必须匹配整行(Bash不会隐式地附加‘*’)。在应用HISTCONTROL指定的检查之后,每个模式会与行进行测试。除了普通的shell模式匹配字符之外,‘&’匹配前一个历史记录行。反斜杠用于转义‘&’;在尝试匹配之前会移除反斜杠。如果多行复合命令的第一行被保存,第二行及后续行将不再进行测试,并且无论HISTIGNORE的值如何,都会添加到历史记录中。如果第一行未被保存,则命令的第二行及后续行也不会被保存。模式匹配会遵循extglob shell选项的设置。
HISTIGNORE包含了HISTCONTROL的一些功能。模式‘&’与ignoredups相同,而模式‘[ ]*’与ignorespace相同。将这两种模式结合在一起,用冒号分隔,可实现ignoreboth的功能。
HISTSIZE 历史列表中要记住的最大命令数。如果值为0,命令不会保存到历史列表中。小于零的数值会导致每条命令都被保存到历史列表中(没有限制)。Shell 在读取任何启动文件后将默认值设置为500。
$ echo $HISTSIZE
1000
💡 HISTSIZE 控制当前会话内存中的历史记录条数, HISTFILESIZE 控制历史文件中保存的记录条数。
HISTTIMEFORMAT 如果设置了该变量且不为 null,其值将作为 strftime(3) 的格式字符串,用于打印 history 内置命令显示的每个历史条目关联的时间戳。如果设置了此变量,shell 会将时间戳写入历史文件,以便在不同的 shell 会话之间保存。这使用历史注释字符将时间戳与其他历史行区分开来。
此参数默认值为空,即不记录时间。
HOSTFILE 包含一个文件的名称,其格式与 /etc/hosts 相同,当 shell 需要完成主机名时应读取该文件。在 shell 运行期间,可能的主机名完成列表可能会发生变化;当值被更改后,下次尝试主机名完成时,Bash 会将新文件的内容添加到现有列表中。如果设置了 HOSTFILE,但没有值,或者指定的文件不可读,Bash 会尝试读取 /etc/hosts 以获取可能的主机名完成列表。当 HOSTFILE 未设置时,Bash 会清除主机名列表。
HOSTNAME 当前主机的名称。
$ echo $HOSTNAME
ol9-vagrant
HOSTTYPE 描述 Bash 所运行机器的字符串。
$ echo $HOSTTYPE
x86_64
$ arch
x86_64
$ uname -p
x86_64
$ uname -m
x86_64
$ echo ${MACHTYPE%%-*}
x86_64
IGNOREEOF 控制 Shell 在接收到 EOF 字符作为唯一输入时的行为。如果设置了该变量,其值表示在 Bash 退出之前,可以作为输入行第一个字符读取的连续 EOF 字符数量。如果变量已设置但没有数值,或者值为空,则默认值为 10。如果变量未设置,则 EOF 表示 Shell 输入的结束。此变量仅在交互式 Shell 中有效。
INPUTRC Readline 初始化文件的名称,会覆盖默认的 ~/.inputrc。
INSIDE_EMACS 如果 Bash 在启动时在环境中找到该变量,它会假定 shell 正在 Emacs 的 shell 缓冲区中运行,并可能根据 TERM 的值禁用行编辑。
LANG 用于确定任意未通过以 LC_ 开头的变量具体选择的类别的本地化类别。
$ echo $LANG
en_US.utf-8
$ locale
LANG=en_US.utf-8
LC_CTYPE="en_US.utf-8"
LC_NUMERIC="en_US.utf-8"
LC_TIME="en_US.utf-8"
LC_COLLATE="en_US.utf-8"
LC_MONETARY="en_US.utf-8"
LC_MESSAGES="en_US.utf-8"
LC_PAPER="en_US.utf-8"
LC_NAME="en_US.utf-8"
LC_ADDRESS="en_US.utf-8"
LC_TELEPHONE="en_US.utf-8"
LC_MEASUREMENT="en_US.utf-8"
LC_IDENTIFICATION="en_US.utf-8"
LC_ALL=
LC_ALL 此变量会覆盖 LANG 以及任何其他指定区域类别的 LC_ 变量的值。
💡 locale设置的优先级从高到低为:LC_ALL > LC_xxx > LANG
LC_COLLATE 此变量决定在排序文件名扩展结果时使用的排序顺序,并且决定了在文件名扩展和模式匹配中范围表达式、等价类和排序序列的行为(见文件名扩展)。
LC_CTYPE 此变量决定字符的解释方式以及在文件名扩展和模式匹配中字符类的行为(见文件名扩展)。
LC_MESSAGES 此变量决定用于翻译由 ‘$’ 前缀的双引号字符串的本地化设置(见特定于本地化的翻译)。
LC_NUMERIC 此变量决定用于数字格式化的本地类别。
LC_TIME 此变量决定用于日期和时间格式化的本地类别。
LINENO 当前正在执行的脚本或 shell 函数中的行号。行号从 1 开始。当不在脚本或函数中时,该值不一定有意义。如果 LINENO 未设置,它会失去其特殊属性,即使随后重新设置也一样。
示例见 BASH_LINENO。
LINES 由 select 命令使用,用于确定打印选择列表的列长度。如果启用了 checkwinsize 选项(参见 The Shopt Builtin),或者在交互式 shell 中收到 SIGWINCH 信号,则会自动设置。
示例见 COLUMNS。
MACHTYPE 一个字符串,用于完整描述 Bash 所运行的系统类型,采用标准的 GNU cpu-company-system 格式。
$ echo $MACHTYPE
x86_64-redhat-linux-gnu
MAILCHECK 指定 shell 检查 MAILPATH 或 MAIL 变量中指定文件的邮件的频率(以秒为单位)。默认值是 60 秒。当需要检查邮件时,shell 会在显示主提示符之前进行检查。如果该变量未设置,或设置为非零或非数字值,shell 将禁用邮件检查。
$ echo $MAILCHECK
60
MAPFILE 一个数组变量,用于存储 mapfile 内建命令读取的文本,当未提供变量名时使用此数组。
$ cat > config.cfg << 'EOF'
# database server configuration file
SERVER_NAME=amigo
# listening port
PORT=1521
DATABASE=oracle
MAX_CONNECTIONS=100
EOF
$ mapfile -t <<< $(grep -v '^#' config.cfg)
$ echo ${MAPFILE[@]}
SERVER_NAME=amigo PORT=1521 DATABASE=oracle MAX_CONNECTIONS=100
$ echo ${#MAPFILE[@]}
4
OLDPWD 由 cd 内置命令设置的上一个工作目录。
$ pwd
/home/vagrant/test
$ cd /usr/include
$ echo $OLDPWD
/home/vagrant/test
OPTERR 如果设置为值 1,Bash 会显示 getopts 内置命令生成的错误信息(若为0,则不显示)。每次调用 shell 时,OPTERR 都会被初始化为 1。
$ echo $OPTERR
1
OSTYPE 描述 Bash 所运行操作系统的一个字符串。
$ echo $OSTYPE
linux-gnu
$ echo ${MACHTYPE#*-*-}
linux-gnu
PIPESTATUS 一个数组变量(参见数组),包含最近执行的前台管道中各个命令的退出状态值列表,该管道可能仅包含一个简单命令(参见Shell命令)。Bash在执行多元素管道、定时和取反管道、简单命令、使用’('运算符创建的子shell、[[和((复合命令,以及导致Shell中止命令执行的错误条件后,会设置PIPESTATUS。
$ (exit 3) | (exit 1) | (exit 2)
$ echo ${PIPESTATUS[@]}
3 1 2
POSIXLY_CORRECT 如果在 Bash 启动时环境中存在此变量,shell 会在读取启动文件之前进入 POSIX 模式(参见 Bash 和 POSIX),就好像提供了 –posix 调用选项。如果在 shell 运行时设置此变量,Bash 会启用 POSIX 模式,就像执行了以下命令。当 Shell 进入 POSIX 模式时,如果该变量尚未设置,则会设置它。
set -o posix
示例:
$ echo $POSIXLY_CORRECT
$ set -o posix
$ echo $POSIXLY_CORRECT
y
$ set +o posix
$ echo $POSIXLY_CORRECT
$
PPID Shell 父进程的进程 ID。此变量为只读。
$ echo $$
16797
$ ps -p 16797 -o ppid
PPID
16796
$ echo $PPID
16796
PROMPT_COMMAND 如果设置了此变量,且它是一个数组,则每个已设置元素的值在打印主提示符 ($PS1) 之前被解释为要执行的命令。如果设置了此变量但不是数组变量,则其值将用作要执行的命令。
$ echo $PROMPT_COMMAND
printf "\\033]0;%s@%s:%s\\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\\~}"
$ echo ${#PROMPT_COMMAND[@]}
1
💡 \\033]是控制台的OSC序列,参见man console_codes。\\033]0;是修改窗口标题和图标名称。\\007是序列的终止符。
如果你单独执行以上printf命令,似乎窗口标题没变,这实际是一种错觉。这是由于输出成功后马上被终端覆盖了。这是就体现出PROMPT_COMMAND的优势,因为每次都会执行:
# 窗口标题实际改变了,只不过你观察不到
printf "\\033]0;WINDOW TITLE\\007"
# 在5秒期间,你可以看到窗口标题变量
printf "\\033]0;WINDOW TITLE\\007";sleep 5
# 赋值给变量,就可永久成功设置标题
export PROMPT_COMMAND='printf "\\033]0;WINDOW TITLE\\007"'
PROMPT_DIRTRIM 如果设置为大于零的数字,则该值用于确定在展开 w 和 W 提示符字符串转义时保留的末尾目录组件的数量(参见控制提示符)。被删除的字符将替换为省略号。
PS0 这个参数的值像 PS1 一样展开,并在交互式 shell 读取命令后且命令执行前显示。
PS3 这个变量的值用作 select 命令的提示符。如果未设置此变量,select 命令将使用 ‘#? ’ 提示。
PS4 这个参数的值像 PS1 一样展开,展开后的值是在设置了 -x 选项时(参见 Set 内置命令)命令行回显前显示的提示符。展开值的第一个字符会根据需要重复多次,以指示多级间接。默认值为 ‘ ’。
$ echo $PS4
+
$ set -x
++ printf '\\033]0;%s@%s:%s\\007' vagrant ol9-vagrant /usr/include
$ set +x
+ set +x
PWD 当前工作目录,由 cd 内置命令设置。
$ echo $PWD
/home/vagrant/test
$ cd /usr/include
$ echo $PWD
/usr/include
RANDOM 每次引用此参数时,它会扩展为介于 0 和 32767 之间的随机整数。为 RANDOM 分配一个值会初始化(设定种子)随机数序列。使用相同的常量值为随机数生成器设定种子会产生相同的值序列。如果 RANDOM 被取消设置,即使随后重新设置,它也会失去其特殊属性。
$ echo $RANDOM
6952
$ echo $RANDOM
8612
## generate number beween 1 and 1000
$ echo $(($RANDOM % 1000 + 1))
158
$ echo $(($RANDOM % 1000 + 1))
300
READLINE_ARGUMENT 在调用使用 ‘bind -x’ 定义的 Readline 命令时,给定的任何数字参数(参见 Bash 内建命令)。
READLINE_LINE Readline 行缓冲区的内容,用于 ‘bind -x’(参见 Bash 内建命令)。
READLINE_MARK Readline 行缓冲区中标记(保存的插入点)的位置,用于 ‘bind -x’(参见 Bash 内建命令)。插入点与标记之间的字符通常称为区域。
READLINE_POINT Readline 行缓冲区中插入点的位置,用于 ‘bind -x’(参见 Bash 内建命令)。
REPLY read 内建命令的默认变量;在 read 没有提供变量名参数时,设置为读取的行。
$ read -sp "Please input password:"
Please input password:$
$ echo $REPLY
alibaba
SECONDS 这个变量会扩展为自 shell 启动以来的秒数。对该变量的赋值会将计数重置为所赋的值,扩展后的值将变为所赋值加上自赋值以来的秒数。启动 shell 时的秒数和当前时间总是通过以一秒分辨率查询系统时钟来确定。如果 SECONDS 未设置,它将失去特殊属性,即使之后重新设置也不例外。
$ echo $SECONDS
3526
$ uptime -p
up 8 hours, 14 minutes
💡 是shell启动的时间,不是系统启动的时间
SHELL 这个环境变量会扩展为 shell 的完整路径名。如果在 shell 启动时它未被设置,Bash 会将其赋值为当前用户登录 shell 的完整路径名。
$ echo $SHELL
/bin/bash
SHELLOPTS 一个用冒号分隔的已启用 shell 选项列表。列表中的每个单词都是 set 内置命令的 -o 选项的有效参数(见内置命令 Set)。出现在 SHELLOPTS 中的选项是通过 ‘set -o’ 报告为“on”的选项。如果该变量在 Bash 启动时存在于环境中,shell 会在读取任何启动文件之前启用列表中的每个选项。如果该变量被导出,子 shell 会启用列表中的每个选项。该变量为只读。
$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
$ set -o |grep on$
braceexpand on
emacs on
hashall on
histexpand on
history on
interactive-comments on
monitor on
💡 注意SHELLOPTS 和 BASHOPTS 的区别。
SHLVL 每次启动一个新的 Bash 实例时,该值会增加一。它用于计算你的 Bash shell 嵌套的深度。
$ echo $SHLVL
1
$ bash
$ echo $SHLVL
2
$ exit
exit
$ echo $SHLVL
1
SRANDOM 每次引用此变量时,它会扩展为一个 32 位伪随机数。在支持 /dev/urandom 或 arc4random 的系统上,随机数生成器不是线性的,因此每个返回的数字与前面的数字没有关系。该随机数生成器无法设置种子,因此对该变量的赋值没有效果。如果 SRANDOM 未设置,它将失去特殊属性,即使随后重新设置也不例外。
$ echo $SRANDOM
1220798808
TIMEFORMAT 此参数的值用作格式字符串,用于指定以 time 关键字为前缀的管道的计时信息应如何显示。‘%’字符引入一个转义序列,该序列会被展开为时间值或其他信息。转义序列及其含义如下;方括号表示可选部分。
%% 一个字面上的‘%’。
%[p][l]R 以秒为单位的已用时间。
%[p][l]U 在用户模式下消耗的CPU秒数。
%[p][l]S 在系统模式下消耗的CPU秒数。
%P CPU 百分比,计算方式为 (%U %S) / %R。
可选的 p 是一个数字,用于指定精度,即小数点后的分数位数。值为 0 时不会输出小数点或小数部分。time 最多打印小数点后六位数字;p 值大于 6 时会被改为 6。如果未指定 p,time 会打印小数点后三位数字。
可选的 l 指定更长的格式,包括分钟,形式为 MMmSS.FFs。p 的值决定是否包括小数部分。
如果未设置此变量,Bash 会当作其具有以下值处理:
$'\\nreal\\t%3lR\\nuser\\t%3lU\\nsys\\t%3lS'
如果值为 null,Bash 不会显示任何时间信息。当显示格式字符串时,会在末尾添加换行符。
$ echo $TIMEFORMAT
$ time sleep 1
real 0m1.205s
user 0m0.000s
sys 0m0.002s
$ TIMEFORMAT='%R'
$ time sleep 2
2.002
注意,这里说的time是bash的keyword,而非GNU版本的time。后者需要单独安装。
$ which time
/usr/bin/which: no time in (/home/vagrant/.local/bin:/home/vagrant/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin)
$ yum search time
Last metadata expiration check: 3 days, 2:28:42 ago on Fri 09 Jan 2026 08:19:10 AM UTC.
======================================================================== Name Exactly Matched: time ========================================================================
time.src : A GNU utility for monitoring a program's use of system resources
time.x86_64 : A GNU utility for monitoring a program's use of system resources
...
$ sudo yum -y install time
$ which time
/usr/bin/time
$ time -f "Real time: %E" sleep 1
-bash: -f: command not found
real 0m0.001s
user 0m0.000s
sys 0m0.001s
$ /usr/bin/time -f "Real time: %E" sleep 1
Real time: 0:01.05
TMOUT 如果设置为大于零的值,read 内置命令将使用该值作为默认超时时间(参见 Bash 内置命令)。当输入来自终端时,如果在 TMOUT 秒后没有输入,select 命令(参见条件构造)将终止。
在交互式 shell 中,该值被解释为在发出主提示符后等待输入行的秒数。如果在等待该秒数后没有收到完整的输入行,Bash 将终止。
正确的示例:
$ echo $SHLVL
1
$ bash
$ echo $SHLVL
2
$ TMOUT=2 read -p "please input:"
please input:$
$ echo $SHLVL
2
$ echo $TMOUT
$ exit
exit
错误的示例,区别在于TMOUT=2后有分号:
$ echo $SHLVL
1
$ bash
$ echo $SHLVL
2
$ TMOUT=2; read -p "please input:"
timed out waiting for input: auto-logout
$ echo $TMOUT
$ echo $SHLVL
1
TMPDIR 如果设置了该变量,Bash 将使用其值作为目录名称,在该目录中 Bash 为 shell 使用创建临时文件。
$ echo $TMPDIR
UID 当前用户的数字实际用户 ID。该变量为只读。
$ echo $UID
1000
$ id -u
1000



