这篇文章介绍一下Bash中的环境变量PROMPT_COMMAND。
PROMPT_COMMAND 是什么
PS1-PS4介绍了一些用于提示信息控制的环境变量,而在此之前可以进行回调的一个环境变量就是PROMPT_COMMAND,这个环境变量中设定的内容将在交互式脚本的提示(PS1)出现之前被执行。
PS1-4介绍
关于环境变量PS1的使用介绍可以参看:
PROMPT_COMMAND使用示例:执行顺序说明
以如下环境中的Bash为例进行使用的说明
[root@liumiaocn ~]# echo $SHELL
/bin/bash
[root@liumiaocn ~]# bash --version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 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.
[root@liumiaocn ~]#
[root@liumiaocn ~]#
[root@liumiaocn ~]# echo $PS1
[\u@\h \W]\$
[root@liumiaocn ~]#
设定如下的PROMPT_COMMAND
[root@liumiaocn ~]# export PROMPT_COMMAND="Hello LiuMiao"
-bash: Hello: command not found
[root@liumiaocn ~]#
command not found的提示说明了两件事情:
- 首先export命令只是一个环境变量设定和输出的过程,不会有产生command not found的动作。所以此错误信息是PROMPT_COMMAND的机制产生的,它会在用户交互的提示信息出现之间将设定在其中的内容作为可执行的命令执行。
- 其次,设定在PROMPT_COMMAND的内容执行的时间点在出现提示符(PS1所设定的内容)之前。
进行如下重新设定,可以看到设定内容已经即时生效了。
[root@liumiaocn ~]# export PROMPT_COMMAND="echo Hello LiuMiao "
Hello LiuMiao
[root@liumiaocn ~]#
进行任何操作都会首先执行此命令,比如:
[root@liumiaocn ~]# hostname
liumiaocn
Hello LiuMiao
[root@liumiaocn ~]#
PROMPT_COMMAND使用示例:macOS的Terminal设定
如果使用macOS本身的终端,可以看到在Bash下,PROMPT_COMMAND的设定如下所示:
liumiaocn:~ liumiao$ echo $SHELL
/bin/bash
liumiaocn:~ liumiao$ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19)
Copyright (C) 2007 Free Software Foundation, Inc.
liumiaocn:~ liumiao$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.2
BuildVersion: 19C57
liumiaocn:~ liumiao$
liumiaocn:~ liumiao$ echo $PROMPT_COMMAND
update_terminal_cwd
liumiaocn:~ liumiao$
这本身就是PROMPT_COMMAND的一个使用示例,update_terminal_cwd是一个函数,我们来看一下它是在何处被定义的。首先Bash会使用全局设定的/etc/bashrc中设定的内容
liumiaocn:~ liumiao$ cat /etc/bashrc
# System-wide .bashrc file for interactive bash(1) shells.
if [ -z "$PS1" ]; then
return
fi
PS1='\h:\W \u\$ '
# Make bash check its window size after a process completes
shopt -s checkwinsize
[ -r "/etc/bashrc_$TERM_PROGRAM" ] && . "/etc/bashrc_$TERM_PROGRAM"
liumiaocn:~ liumiao$
可以看到/etc/bashrc_*的文件如下所示:
liumiaocn:~ liumiao$ ls /etc/bashrc_*
/etc/bashrc_Apple_Terminal
liumiaocn:~ liumiao$
在这个文件之中就有update_terminal_cwd函数的定义
if [ -z "$INSIDE_EMACS" ]; then
update_terminal_cwd() {
# Identify the directory using a "file:" scheme URL, including
# the host name to disambiguate local vs. remote paths.
# Percent-encode the pathname.
local url_path=''
{
# Use LC_CTYPE=C to process text byte-by-byte. Ensure that
# LC_ALL isn't set, so it doesn't interfere.
local i ch hexch LC_CTYPE=C LC_ALL=
for ((i = 0; i < ${#PWD}; ++i)); do
ch="${PWD:i:1}"
if [[ "$ch" =~ [/._~A-Za-z0-9-] ]]; then
url_path+="$ch"
else
printf -v hexch "%02X" "'$ch"
# printf treats values greater than 127 as
# negative and pads with "FF", so truncate.
url_path+="%${hexch: -2:2}"
fi
done
}
printf '\e]7;%s\a' "file://$HOSTNAME$url_path"
}
PROMPT_COMMAND="update_terminal_cwd${PROMPT_COMMAND:+; $PROMPT_COMMAND}"
fi
另外,利用此特性还可以记录用户的操作内容,虽然稍微复杂一点的场景下就不太适合,但是通过这些加深对此环境变量的理解。