简介
在管理 Linux 服务器时,您将花费大量时间使用命令行。对于大多数人来说,这意味着与 Bash shell 一起花费大量时间。
虽然大多数发行版为用户和 root 提供了合理的默认提示样式,但自定义提示以添加自己的偏好可能会很有帮助。您可以包含许多有用的信息,这些信息可以帮助您保持方向感,并在您使用提升的特权时提醒您。
我们将使用 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 提示的内容。
Bash 通过使用 PS1
和 PS2
环境变量来配置其提示。
PS1 定义了您将看到的主提示。每次登录时都会看到这个。在 Ubuntu 系统中,默认情况下应该是这种形式:
用户名@主机名: 当前目录$
请注意末尾的 $
。这表示 shell 是普通用户 shell。对于 root 用户,这将被替换为 #
,以区分并提醒您正在使用提升的特权。
PS2 提示用于多行命令。您可以通过在终端中键入以下内容来查看当前的 PS2 变量设置:
echo \
在反斜杠后直接按回车键以查看提示。在 Ubuntu 中,默认值为 >
。
通常,我们在我们的 ~/.bashrc
文件中定义这些变量将保存在哪里,该文件在我们的交互式 shell 启动时读取。
在 Ubuntu 12.04 的此文件中,我们可以找到类似以下部分:
# 如果终端具有此功能,则取消注释以获得彩色提示;默认情况下关闭以不分散用户的注意力:终端窗口的焦点应该放在命令的输出上,而不是提示上 # force_color_prompt=yes if [ -n "$force_color_prompt" ]; then if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then # 我们有颜色支持;假设它符合 Ecma-48(ISO/IEC-6429)的规范。(缺乏此类支持非常罕见,这种情况往往支持 setf 而不是 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
行。现在执行此操作以利用我们稍后将进行的自定义。
force_color_prompt=yes
我们关心的部分是设置提示的部分。这是嵌套在一个 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
的部分指示,如果您正在更改根环境中操作,提示将被修改以提醒您。您可能希望保持提示的这一部分不变,因为这是一个有用的功能。
提示定义的其余部分如下:
\u@\h:\w\$:
这描述了我们一直在看到的主提示,使用了一些转义序列。
Bash 转义序列
我们可以在 Bash 手册页中找到一整个可能的转义序列列表:
\a 一个 ASCII 响铃字符 (07)
\d 以 "Weekday Month Date" 格式显示的日期(例如,“Tue May 26”)
\D{format}
将格式传递给 strftime(3),并将结果插入到提示字符串中;空格式会产生一个特定于区域设置的时间表示。大括号是必需的
\e 一个 ASCII 转义字符 (033)
\h 主机名直到第一个 `.`
\H 主机名
\j 当前 shell 管理的作业数
\l shell 终端设备名称的基本名称
\n 换行
\r 回车
\s shell 的名称,$0 的基本名称(最后一个斜杠后面的部分)
\t 当前时间以 24 小时 HH:MM:SS 格式显示
\T 当前时间以 12 小时 HH:MM:SS 格式显示
\@ 当前时间以 12 小时 am/pm 格式显示
\A 当前时间以 24 小时 HH:MM 格式显示
\u 当前用户的用户名
\v bash 的版本(例如,2.00)
\V bash 的发布版本,版本 + 补丁级别(例如,2.00.0)
\w 当前工作目录,$HOME 用波浪号缩写(使用 PROMPT_DIRTRIM 变量的值)
\W 当前工作目录的基本名称,$HOME 用波浪号缩写
\! 此命令的历史编号
\# 此命令的命令编号
\$ 如果有效 UID 为 0,则为 #,否则为 $
\nnn 与八进制数字 nnn 对应的字符
\\ 一个反斜杠
\[ 开始一系列不可打印字符,可用于将终端控制序列嵌入到提示中
\] 结束一系列不可打印字符
如您所见,其中包含一些基本信息,以及一些您可能不需要的信息(ASCII 响铃字符、Bash 版本等)。
我们的提示目前包括用户名(\u)、@ 符号、主机名的第一部分(\h)、当前工作目录(\w),最后是普通用户的 “$” 和 root 用户的 “#”。
让我们退出 ~/.bashrc
文件,以便我们可以测试一些其他选项。
测试新的 Bash 提示
尽管最终我们希望编辑 ~/.bashrc
文件以使我们的选择永久生效,但从命令行本身实验更改提示要容易得多。
在开始修改之前,让我们将当前的 PS1
值保存到一个新变量中。这将使我们能够在出错时更轻松地切换回原始提示,而无需注销并再次登录。
ORIG=$PS1
现在,我们有一个名为 ORIG
的环境变量,它将保存我们默认提示的副本。
如果我们需要切换回原始提示,可以输入:
PS1=$ORIG
让我们从简单的开始,只显示用户名和实际提示的 “$”:
PS1="\u$"
我们应该会得到类似于这样的东西:
demouser$
让我们稍微加点空格,使其看起来更好看:
PS1="\u $: "
demouser $:
然而,我们可能不想使用 “$” 字符。我们应该使用 \$
转义序列。这将根据我们是否是 root 动态修改提示,从而使我们的 PS1 在 root 用户下正确使用:
PS1="\u \$: "
我们可以在我们的提示中添加任何文字字符串:
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 $:
这是了解您是否在使用系统资源的好方法。
如果日期或时间对您的提示很重要,您可以尝试类似于以下的内容。让我们也用一些括号和圆括号将我们的数据分隔一下,以保持其组织性。让我们还将 \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 $
有些人不喜欢多行提示,但这是提供提示中更多信息的一种方法。
更改提示符颜色
现在我们已经对影响提示符的不同方式有了很好的了解,让我们尝试一些着色。
Bash 允许您通过使用特殊代码将颜色引入提示符。这些通常会导致混淆,因为所选的代码并不是非常描述性的。
在我们开始实际的颜色代码之前,我们应该讨论一下如何实际实现它们。在 Bash 设置中定义颜色代码有正确和错误的方式。
首先,您必须将整个颜色代码描述包装在 \[
和 \]
标记中。这些括号指示 Bash,应该将第一个序列之后存在的字符视为非打印字符。
Bash 需要知道这一点,以便它可以估计在换行之前允许打印多少字符。如果您不在 \[
和 \]
标记中包含颜色代码,Bash 将计算所有字符为文字字符,并且会过早地换行。
其次,在括号非打印序列内部,您需要通过键入 \e[
或 \033[
来指定颜色提示的开始。这两者都是相同的,表示转义序列的开始。在本指南中,我将使用 \e[
,因为我认为这样更清晰一些。
在 \]
之前,您需要一个 “m” 来指示您正在提供一个颜色序列。
因此,基本上,每当我们想要修改颜色时,我们必须在我们的提示符中输入类似以下的内容:
\[\e[<span class="highlight">颜色信息</span>m\]
正如您所看到的,这是使我们的提示符特别混乱的部分。
至于颜色代码,用于更改前景文本颜色的基本代码如下:
- 30:黑色
- 31:红色
- 32:绿色
- 33:黄色
- 34:蓝色
- 35:紫色
- 36:青色
- 37:白色
您还可以通过在基本值之前设置一个 “属性”(用分号 (😉 分隔)来修改这些基本值。
根据您使用的终端类型,这些行为可能会有所不同。一些常见的属性包括:
- 0:普通文本
- 1:粗体或浅色,取决于终端
- 4:下划线文本
因此,如果您想要带有下划线的绿色文本,您将使用以下序列:
\[\e[4;32m\]
然后我们输入我们想要的提示符。之后,我们可能希望将颜色重置回其原始值,以便在终端中键入的文本不会显示奇怪的颜色。
我们可以通过使用另一个颜色代码来指示 Bash 重置提示符颜色。这个代码是:
\[\e[0m\]
因此,一个带有用户名和主机的简单彩色提示符可能如下所示:
PS1="\[\e[4;32m\]\u@\h\[\e[0m\]$ "
我们还可以为更复杂的情况指定背景颜色。背景颜色不能带有属性。它们是:
- 40:黑色背景
- 41:红色背景
- 42:绿色背景
- 43:黄色背景
- 44:蓝色背景
- 45:紫色背景
- 46:青色背景
- 47:白色背景
尽管您可以一次性指定背景颜色、属性和文本颜色,例如:
\[\e[42;1;36m\]
但通常最好将背景信息与其他信息分开:
\[\e[42m\]\[\e[1;36m\]
有时,如果您只使用 “普通” 文本属性(0),在某些终端中颜色会混乱。您可以通过不使用 0 指定普通值来避免这种情况,因为它本来就是默认值。
使您的提示符更改永久化
现在我们已经玩弄了一段时间的提示符,我们应该对我们想要提示符看起来有了很好的想法。您应该能够创建一个带颜色和一个不带颜色的提示符。
对于我们的示例,我们将使用以下带颜色的提示符:
PS1="[\[\e[0;32m\]\u@\h, load: `cat /proc/loadavg | awk '{ print $1; }'`\[\e[00m\]] (\[\e[00;35m\]\d - \t\[\e[00m\])\n\w \$ "
我们还将使用它的不带颜色的等价物,以便在不希望有彩色的 bash 提示符时使用:
PS1="[\u@\h, load: `cat /proc/loadavg | awk '{ print $1; }'`] (\d - \t)\n\w \$ "
现在我们有了我们想要的提示符的两个版本,我们可以编辑我们的 ~/.bashrc
文件中的 PS1
。
nano ~/.bashrc
正如我们在开头讨论的那样,我们文件中的提示符现在已经包含了功能,以便在 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\]\$ ' <span class="highlight">PS1='${debian_chroot:+($debian_chroot)}'</span> else # PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' <span class="highlight">PS1='${debian_chroot:+($debian_chroot)}'</span> fi unset color_prompt force_color_prompt
在提示符的末尾,在最后一个引号关闭之前,我们可以添加我们想要实现的提示符。实际上,由于我们的提示符使用单引号,我们希望将当前提示符中的引号类型更改为双引号。
在第一个 PS1
赋值中,使用您的提示符的彩色版本。在第二个中,使用不带颜色的版本。
if [ "$color_prompt" = yes ]; then # PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' PS1=<span class="highlight">"</span>${debian_chroot:+($debian_chroot)}<span class="highlight">[\[\e[0;32m\]\u@\h, load: `cat /proc/loadavg | awk '{ print $1; }'`\[\e[00m\]] (\[\e[00;35m\]\d - \t\[\e[00m\])\n\w \$ "</span> else # PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' PS1=<span class="highlight">"</span>${debian_chroot:+($debian_chroot)}<span class="highlight">[\u@\h, load: `cat /proc/loadavg | awk '{ print $1; }'`] (\d - \t)\n\w \$ "</span> fi unset color_prompt force_color_prompt
完成后,我们可以关闭并保存文件。
现在,当您注销并重新登录时,您的提示符将更改为您设置的值。
结论
有许多不同的方法可以个性化您的配置。给某些项目着色可以使它们更加突出,并且可以帮助您在通过终端历史记录时定位最后一个提示符。
另一个流行的想法是为 root 用户提供特殊的提示符,以便对比提醒您的特权。发挥创造力,尝试找到对您来说在有用信息和混乱之间的平衡点。