内容介绍

在管理Linux服务器时,命令行操作无疑是最为耗时的环节。对大多数用户而言,这意味着将大量时间用于操作Bash shell。

尽管大多数发行版都提供默认的用户类型与root prompts,但定制我们自己的prompt无疑有助于引入更多使用偏好。大家可以在其中纳入各类实用信息,帮助自己更有针对性地执行任务并在权限提升时得到提示。

在本示例中,我们将使用Ubuntu 12.04 VPS,但几乎所有现代Linux发行版都遵循类似的操作方法。

验证您的Shell为Bash

在着手定制shell之前,大家应当确认自己的当前shell为Bash。

对于大多数系统而言这一点并不成问题,但有时候某些改造版可能会使用不同的shell,或者有用户利用其测试新shell。

检查/etc/passwd文件即可轻松确认这一点,首先打开该文件:

less /etc/passwd
此文件中的每一行都包含与不同用户相关的信息。在第一列中找到我们的用户及root用户,其间以冒号分隔。在最后一个字段内,默认登录shell为:

root:x:0:0:root:/root:/bin/bash
. . .
demouser:x:1000:1000:,,,:/home/demouser/bin/bash
如果最后字段为/bin/bash, 则设置完成。

如果最后字段并非/bin/bash,大家又希望将默认shell变更为Bash,则可利用root权限编辑此文件并对与用户关联的最后字段加以变更:

sudo nano /etc/passwd
在变更完成后,退出登录并返回以使用Bash shell。

查看当前值

首先,我们先看看配置文件中存在哪些现有Bash prompts定义。

Bash利用PS1与PS2环境变量对其prompt进行配置。

PS1负责定义我们查看到的主prompt。在默认情况下,Ubuntu系统中的格式如下:

username@hostname: current_directory$
请注意结尾处的$号。这意味着该shell属于普通用户shell。对于root用户,结尾处将以#号表示。

PS2 prompt则用于多行命令。大家可以在终端中使用以下命令以查看当前PS2变量:

echo \
直接按下回车以查看该prompt。通常来讲,我们定义的这些变量会保存在~/.bashrc文件当中,其会在我们的互操作shell启动时接受读取。

在Ubuntu 12.04的该文件中,我们可以找到以下部分:

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
# force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi

if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
我们能够以彩色方式标注部分逻辑。大家需要取消force_color_prompt=yes行的注释以实现彩色prompt。这种方式还有其它好处,我们将在稍后具体讨论。

force_color_prompt=yes
这里我们需要关注的是与prompt设置相关的部分。是否使用彩色显示依靠if-else中的嵌套机制实现:

if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
以上部分添加了彩色支持。下面来看第二部分,先排除彩色选项,看看其中的基本内容:

PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
看起来相当复杂,而且存在着一些与常规shell使用似乎并不相关的部分。

其中debian_chroot代表我们是否在变更root环境下进行操作,prompt会被修改以提醒用户。大家可能需要保留这部分提示。

其余部分的prompt定义则为:

\u@\h:\w\$:
这部分负责表明我们在主prompt中使用了部分转义序列。

Bash转义序列

我们可以在Bash指南页面中查看到完整的可用转义序列清单:

\a an ASCII bell character (07)
\d the date in "Weekday Month Date" format (e.g., "Tue May 26")
\D{format}
the format is passed to strftime(3) and the result is inserted into the prompt string; an empty format results in a locale-
specific time representation. The braces are required
\e an ASCII escape character (033)
\h the hostname up to the first `.'
\H the hostname
\j the number of jobs currently managed by the shell
\l the basename of the shell's terminal device name
\n newline
\r carriage return
\s the name of the shell, the basename of $0 (the portion following the final slash)
\t the current time in 24-hour HH:MM:SS format
\T the current time in 12-hour HH:MM:SS format
\@ the current time in 12-hour am/pm format
\A the current time in 24-hour HH:MM format
\u the username of the current user
\v the version of bash (e.g., 2.00)
\V the release of bash, version + patch level (e.g., 2.00.0)
\w the current working directory, with $HOME abbreviated with a tilde (uses the value of the PROMPT_DIRTRIM variable)
\W the basename of the current working directory, with $HOME abbreviated with a tilde
\! the history number of this command
\# the command number of this command
\$ if the effective UID is 0, a #, otherwise a $
\nnn the character corresponding to the octal number nnn
\\ a backslash
\[ begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
\] end a sequence of non-printing characters
如大家所见,其中包含部分基本信息,也有一些我们用不到的信息)ASCII bell字符、Bash版本等)。

我们的prompt目前已经拥有了用户名(\u)、一个@符号、主机名称的第一部分(\h)、当前工作目录(\w)以及用于标注普通用户与root用户的$与#。

下面退出~/.bashrc文件并测试其它选项。

测试新的Bash Prompts

尽管我们最终需要编辑~/.bashrc文件以调整选定参数,但直接通过命令行变更prompt进行效果测试显然更为简便。

在开始着手修改之前,我们将PS1当前值保存在一条新变量中。如此一来,我们就能够在无需退出登录的前提下随时切换回原始prompt。

ORIG=$PS1
现在我们拥有了一条名为ORIG的环境变量,其中保存着prompt的默认副本。如果我们需要切换回初始prompt,则:

PS1=$ORIG
先从简单内容着手,为当前prompt提供用户名与$:

PS1="\u$"
返回结果如下:

demouser$
加上个空格来改善显示效果:

PS1="\u $: "

demouser $:
不过我们可能不想使用$字符,这里可以使用\$转义序列作为替代。我们可以使用root权限对PS1进行直接修改:

PS1="\u \$: "
接下来添加任意希望在prompt中使用的文字字符:

PS1="Hello, my name is \u! \$: "

Hello, my name is demouser! $:
我们也可以利用普通shell功能插入任意命令的执行结果。

在这里,我们可以利用反引号插入命令结果,此结果提取自/proc/loadavg处负载指标的第一列,代表我们服务器的当前负载:

PS1="\u, load: `cat /proc/loadavg | awk '{ print $1; }'` \$: "

demouser, load: 0.01 $:
这样我们就能轻松了解系统的当前工作强度了。

如果大家希望在prompt中关注数据或者时间,也可以采取类似的操作。我们需要利用小括号与中括号对数据位进行分享,同时添加\w保证只追踪当前工作目录:

PS1="[\u@\h, load: `cat /proc/loadavg | awk '{ print $1; }'`] (\d - \t) \w \$ "

[demouser@host, load: 0.01] (Thu Feb 20 - 13:15:20) ~ $
很明显,边种处理方式比较麻烦,特别是在需要在长路径之间进行目录变更的情况下:

cd /etc/systemd/system/multi-user.target.wants

[demouser@host, load: 0.01] (Thu Feb 20 - 13:18:28) /etc/systemd/system/multi-user.target.wants $
如果我们仍然需要完整信息,但希望让命令更短一点,则可以利用\n将两行信息加以拆分:

PS1="[\u@\h, load: `cat /proc/loadavg | awk '{ print $1; }'`] (\d - \t)\n\w \$ "

[demouser@host, load: 0.00] (Thu Feb 20 - 13:20:00)
/etc/systemd/system/multi-user.target.wants $
有些朋友不喜欢使用多行prompt,但这确实能够让我们的prompt容纳更多信息。

变更Prompt颜色

现在我们已经了解了多种prompts调整方式,接下来再给它添加一点色彩。

Bash允许我们使用特定代码在prompt中实现彩色显示。但这通常会带来新的困扰,因为这部分代码的说明内容不够清晰。

在使用色彩调节代码前,我们应当首先了解Bash设置中正确与错误的色彩代码定义方式。

首先,大家必须以[与]作为色彩代码的描述范围。对于Bash,这代表两个括号间的字符为非输出字符。

Bash需要在此基础上估算字符数量,以备后续输出。如果不将色彩代码纳入[与]之间,那么Bash会将全部字符都计为文本字符并在下一行中进行打包。

另外,在括号内的非输出序列中,我们需要输入\e[或者\033[指定彩色prompt的起点。二者的作用相同,都负责指定该反义序列的起始位置。在本示例中,我们将使用\e[。

在]之前,我们还需要使用“m”来表示即将提供一条色彩序列。

基本上,每次进行色彩修改时,我们都需要输入下面这种命令格式:

\[\e[color_informationm\]
可以看到,这会让我们的prompts变得相当凌乱。

下面来看用于变更前景文本颜色的基本代码:

30: Black
31: Red
32: Green
33: Yellow
34: Blue
35: Purple
36: Cyan
37: White
大家也可以通过在以上设定前设置“属性”修改这些基础值,各值之间以分号分隔。

根据实际终端的不同,操作效果也有所区别。部分常见属性包括:

0: 普通文本
1: 在不同终端中可能代表粗体或者浅色显示
4: 下划线文本
因此如果大家希望使用下划线绿色文本,则:

\[\e[4;32m\]
接下来继续正常使用即可。另外,我们也可以随时将色彩重置为初始值。

重置命令如下:

\[\e[0m\]
结合来看,包含有用户名及主机的简单彩色prompt设置方式如下所示:

PS1="\[\e[4;32m\]\u@\h\[\e[0m\]$ "
我们也可以指定背景颜色。背景颜色无法获取属性,具体包括:

40: Black background
41: www.weicaiyule.cc
42: Green background
43: www.wandayl88.cn
44: Blue background
45: Purple background
46: Cyan background
47: White background
不过大家可以一次性指定背景颜色、属性与文本颜色:

\[\e[42;1;36m\]
当然,这里建议各位将背景信息与其它信息分隔开来:

\[\e[42m\]\[\e[1;36m www.yigouyule2.cc\]
在使用普通文本属性(0)时,终端中可能出现一些乱码。如果遇到这种问题,大家最好避免使用0值指定普通属性——由于属于默认值,我们无需额外指定。

永久修改Prompt

在经过一系列摸索后,相信大家已经基本了解到自己喜爱的prompt应该是什么样子。

在本示例中,我们将使用以下彩色prompt:

PS1="[\[\e[0;32m\]\u@\h, load: `cat /proc/loadavg | awk '{ print $1; }'`\[\e[00m\]] (\[\e[00;35m\]\d - \t\[\e[00m\])\n\w \$ "
而在需要使用音色方案时,我们则选择以下配置:

PS1="[\u@\h, load: `cat /proc/loadavg | awk '{ print $1; }'`] (\d - \t)\n\w \$ "
现在我们的两套prompt版本已经就绪,接下来在~/.bashrc文件中编辑PS1。

nano ~/.bashrc
正如文章开头所提到,文件中的各prompts被包含在功能中以适用于chroot环境。这部分内容不要变动,文件内容如下:

if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
注释掉当前PS1分配机制,同时复制其下方的debian_chroot逻辑,修改后内容如下:

if [ "$color_prompt" = yes ]; then
# PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
PS1='${debian_chroot:+($debian_chroot)}'
else
# PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
PS1='${debian_chroot:+($debian_chroot)}'
fi
unset color_prompt force_color_prompt
在该prompt结尾处的最后一个引号之前,我们可以添加希望实现的各prompts。另外,由于我们的prompt使用单引号,因此这里需要变更当前prompt中的引用类型以使用双引号。

在第一条PS1分配内容中使用prompt的彩色版本。而第二条中,使用单色版本。

if [ "$color_prompt" = yes ]; then
# PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
PS1="${debian_chroot:+($debian_chroot)}[\[\e www.yigouyule2.cn/[0;32m\]\u@\h, load: `cat /proc/loadavg | awk '{ print $1; }'`\[\e[00m\]] (\[\e[00;35m\]\d - \t\[\e[00m\])\n\w \$ "
else
# PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
PS1="${debian_chroot:+($debian_c www.xyseo.net hroot)}[\u@\h, load: `cat /proc/loadavg | awk '{ print $1; }'`] (\d - \t)\n\w \$ "
fi
unset color_prompt www.feifanyule.cn force_color_prompt
完成后保存并退出。

现在在退出登录并重新登录时,我们的prompt即会根据所设定值进行变更。

总结

我们可以通过多种方式实现个性化配置,而对特定条目进行彩色显示也有助于翻阅过程中及时关注重要内容。

另一种比较流行的作法是为root用户提供特殊效果提示,从而提醒大家当前正处于特权操作模式。当然,各位也可以充分发挥想象力,帮助自己更为高效地在混乱的工作中找到真正值得关注的信息。

本文来源自DigitalOcean Community。英文原文:How to Customize your Bash Prompt on a Linux VPS By Justin Ellingwood

05-11 22:10