(015) Linux之定制提示符
十年运维系列之基础篇 - Linux
作者:曾林
联系:1494445739@qq.com
版权:文章未经同意请勿转载
一、引言
本小节将讲解一个Linux shell的小特性:shell提示符。和Linux中很多程序一样,shell提示符的可配置型很高。通过介绍,我们会发现shell和终端仿真器程序的内部工作机制。
二、提示符的分解
系统的默认提示符看起来如下所示:
可以看到提示符中包含了用户名、主机名和当前的工作目录。提示符是由名为PS1(prompt string 1的缩写,即提示符字符串1)的环境变量定义的。注意:如果输出的结果同上图范例不同,也不需要担心。每一个Linux发行版本对此提示符字符串的定义都会有所不同,有一些甚至定义得很奇怪。
由上图可以看出,PS1包含了一些提示符中出现的符号,比如方括号、@符号和$符号,但是其余的部分则令人困惑。下图将具体解释一下shell提示符中使用的转义字符。
转义字符 | 含义 |
\a | ASCII铃声。在遇到该转义字符时,计算机将发出哗哗声 |
\d | 当前日期,以星期、月、日的形式表示,如“Mon May 26” |
\h | 本地机器的主机名,但是不带域名 |
\H | 完整的主机名 |
\j | 当前shell会话中进行的任务个数 |
\l | 当前终端设备的名称 |
\n | 换行符 |
\r | 回车符 |
\s | shell程序的名称 |
\t | 当前时间(24小时制),格式为小时:分钟:秒 |
\T | 当前时间(12小时制) |
\@ | 当前时间(12小时制,格式为AM/PM) |
\A | 当前(24小时制),格式为小时:分钟 |
\u | 当前用户的用户名 |
\v | shell的版本号 |
\V | shell的版本号和发行号 |
\w | 当前工作目录名 |
\W |
当前工作目录名称的最后一部分 |
\! | 当前命令的历史编号 |
\# | 当前shell会话中输入的命令数 |
\$ | 在非管理员权限下输出“$”。在管理员权限下输出“#” |
\[ | 标志一个或多个非打印字符序列的开始。用于签入非打印的控制字符,使其以一定方式操作终端仿真器,比如移动光标或更改文本颜色 |
\] | 标志着非显示字符序列的结束 |
三、尝试设计提示符
通过上面shell提示符的转义字符表,我们可以更改提示符来查看效果。比如有下面的设计场景:
$ PS1="\a\$ "
这样以来,每当系统显示提示符的时候,用户都会听到哗哗声。虽然这可能招致用户的心烦,但是有一些情况下却是非常有用的。比如可以用来在一个耗时特别长的命令执行完毕来通知用户。下面是一个稍微复杂一点的场景:
$ PS1="\A \h \$ "
该场景创建了一个信息丰富的提示符,提示包括主机名和当天的时间信息。如果我们需要记录某些任务或者程序的执行时间,在提示符中添加时间信息会比较有用。
四、添加颜色
大多数终端都会响应某些非打印字符序列,来控制光标位置、字符属性(如颜色、粗体、文本闪烁等)等内容。这里先介绍如何使用命令来使终端显示出字符颜色。
字符颜色是由发送到终端仿真器的一个ANSI转义代码来控制的,该转义代码嵌入到了要显示的字符流中。控制代码不会“打印”到屏幕上,而是被终端解释成一条指令。在上面中我们曾经介绍过字符“\[”和“\]”这两个序列用来封装非打印字符串。一个ANSI转义代码以八进制033(该代码由转义键【escape key】)开始,后面跟着一个可选的字符属性,之后是一条指令。例如,将文本颜色设置为正常(attribute=0)、黑色的代码是\033[0;30m。
下表中列出了可用的文本颜色。需要注意的是,这些颜色分为两组,区别在于是否应用了粗体(bold)属性(1),这个属性使得色彩分为深色和浅色。
字符序列 | 文本颜色 |
\033[0;30m | 黑色 |
\033[0;31m | 红色 |
\033[0;32m | 绿色 |
\033[0;33m | 棕色 |
\033[0;34m | 蓝色 |
\033[0;35m | 紫色 |
\033[0;36m | 青色 |
\033[0;37m | 淡灰色 |
\033[1;30m | 深灰色 |
\033[1;31m | 淡红色 |
\033[1;32m | 淡绿色 |
\033[1;33m | 黄色 |
\033[1;34m | 淡蓝色 |
\033[1;35m | 淡紫色 |
\033[1;36m | 淡青色 |
\033[1;37m | 白色 |
现在让我们尝试来创造红色的提示符。我们将相应的转义代码插入到提示符的开端。设置代码如下:
shell> PS1="\[\033[0;31m\][\u@\h \W]\$ "
执行结果如下图:
由上图可见,现在终端针对字符的颜色发生了变化,从默认的白色变成了红色。但是此时用户输入的所有文字和执行结果都变成了红色。要修复这个问题,可以在提示符的末尾插入另外一条转义码来通知终端仿真器恢复到了原来的颜色。改动后的代码如下:
shell> PS1="\[\033[0;31m\][\u@\h \W]\$ \[\033[0m\]"
执行结果如下图:
下表中的代码可以用来设置文本的背景颜色,要注意背景颜色不支持粗体属性:
字符序列 | 背景颜色 |
\033[0;40m | 黑色 |
\033[0;41m | 红色 |
\033[0;42m | 绿色 |
\033[0;43m | 棕色 |
\033[0;44m | 蓝色 |
\033[0;45m | 紫色 |
\033[0;46m | 青色 |
\033[0;47m | 淡灰色 |
下图展示创建红色背景的提示符:
注意:文本除了正常(0)和粗体(1)属性外,还可以设置下划线(4)、闪烁(5)和斜体(7)。当然为了维持好的品味,许多终端仿真器拒绝使用闪烁属性。
五、移动光标
转义代码也可以用来定位光标。比如在提示符出现的时候,这些转义代码通常用来在屏幕的不同位置(比如屏幕上方的一角)显示一个时钟或其他信息。下表所示可以定义光标的转义代码。
转义码 | 动作 |
\033[1;cH | 将光标移动至1行c列 |
\033[nA | 将光标向上移动n行 |
\033[nB | 将光标向下移动n行 |
\033[nC | 将光标向前移动n个字符 |
\033[nD | 将光标向后移动n个字符 |
\033[2J | 清空屏幕并将光标移动至左上角(第0行第0列) |
\033[K | 清空当前光标位置到行末的位置 |
\033[s | 存储当前光标位置 |
\033[u | 恢复之前存储的光标位置 |
通过使用这些代码,用户可以构建这样的一条提示符。每当提示符出现时,屏幕的上方会绘制出一条红色的横条,横条中有用黄色文本显示的时间。用于提示符的编码就是下面一个看起来很可怕的字符串。
shell> PS1="\[\033[s\033[0;41m\033[K\033[1;33m\t\033[0m\033[u\][\u@\h \W]\$ "
执行结果如下图所示:
下表分析一下这个字符串中每一部分的作用。
字符序列 | 动作 |
\[ | 开始一个非打印字符序列。其真正的目的是为了让bash正确计算可见提示符的长度。如果没有该字符,命令行编辑功能无法正确定位光标 |
\033[s | 存储光标位置。在屏幕的顶部横条绘制成并显示时间后,读取并使光标返回此位置。需要注意的是,一些终端仿真器不支持该代码。 |
\033[0;0H | 将光标移动至左上角,即第0行第0列 |
\033[0;41m | 将背景颜色设置为红色 |
\033[K | 将光标当前位置(左上角)到行末的内容清空。因为现在背景颜色已经是红色了,所以清空后的行就是红色,也就绘制出了红色的横条。需要注意的是,清空行的内容并不会改变光标的位置,光标仍然处于屏幕左上角 |
\033[1;33m | 将文本颜色设置为黄色 |
\t | 显示当前时间。尽管这是一个可打印的元素,但是还是将其包含在提示符非打印部分中,这是因为bash在计算可见提示符的长度时,不应当将其计算在内 |
\033[0m | 关闭颜色。对文本和背景均有效 |
\033[u | 恢复之前光标存储的光标位置 |
\] | 结束非打印的字符序列 |
[\u@\h \W]\$ | 提示符字符串 |
六、保存提示符
很显然,用户不会想要每次都输入这样一长串代码,所以就需要将提示符存储在某个地方。将提示符添加到.bashrc文件中是一个一劳永逸的解决方法,也就是将以下两行代码添加到.bashrc文件中。
PS1="\[\033[s\033[0;41m\033[K\033[1;33m\t\033[0m\033[u\][\u@\h \W]\$ "
export PS1