专栏首页用户1880875的专栏深入了解定制 Bash | Linux 中国

深入了解定制 Bash | Linux 中国

Bash 概览

Bash 参考手册中写道:

根本上来说,shell 只是一个能执行命令的宏处理器。宏处理器这个词意味着通过扩展文本跟符号,从而构成更复杂的表达式。 Bash 参考手册 第五版,Bash 5.0 2019 年 5 月

除了能使用其它程序之外,Bash shell 还含有一些内置命令和关键字。Bash 内置功能很强大,甚至能够作为一门 高级语言 独当一面。Bash 的几个关键字和操作符类似于 C 语言

Bash 能够以交互式或非交互式模式启动。Bash 的交互模式是一个很多人都熟悉的典型的终端/命令行界面。GNOME 终端 默认以交互模式打开 Bash。Bash 在非交互模式下运行的例子是,当命令和数据从文件或 shell 脚本通过 管道 传送到 Bash 时。其它 Bash 可以运行的模式包括: 登录(login)非登录(non-login)远程(remote)、POSIX、Unix sh、 受限(restricted),以及使用与用户不同的 UID/GID 模式。各种模式是可以相互组合的。比如,交互式 + 受限 + POSIX 或者非交互式 + 非登录 + 远程。不同的启动模式,决定着 Bash 所读取的启动文件。理解这些操作模式,有助于帮助我们修改启动文件。

根据 Bash 参考手册,它会:

  1. 从文件中...、从作为 -c 调用选项传入参数的字符...,或者从用户的终端中读取输入。
  2. 将输入分解成单词和操作符,遵循 [它的] 引用规则。...这些标记使用元字符隔开。这一步执行别名展开。
  3. 将标记解析成简单与复合命令。
  4. 执行各种 shell 展开...,将展开之后的标记分解成文件名...以及命令和参数的列表。
  5. 执行必要的重定向...并从参数列表中去除重定向操作符及其操作数。
  6. 执行命令。
  7. 必要时等待命令完成,并收集退出状态。

Bash 参考文档 第五版,Bash 版本 5.0 2019 年 5 月

当用户开启终端模拟器进入命令行环境时,便启动了一次交互式 shell 会话。GNOME 终端默认以非登录模式为用户打开 Shell。你可以在 “ 编辑 → 首选项 → 配置文件 → 命令(Edit → Preferences → Profilles → Command)” 中配置 GNOME 终端以何种模式(登录与非登录式)启动。也可以在 Bash 启动时通过向其传递 -login 标志来要求进入登录模式。要注意一点,Bash 的登录模式与非交互模式并不互斥。可以让 Bash 同时以登录模式和非交互模式运行。

启动 Bash

除非传入 -noprofile 选项,否则登录模式的 Bash shell 会默认读取并执行某些初始化文件中命令。如果 /etc/profile 存在,它会是第一个被执行的文件,紧接着是按 ~/.bash_profile~/.bash_login~/.profile顺序找到的第一个文件。当用户退出登录模式的 shell 时,或者有脚本在非交互式登录模式的 shell 中调用了内置 exit命令,Bash 会读取并执行 ~/.bash_logout 中的命令,如果 /etc/bash_logout 存在的话,会紧接着执行它。通常来说,/etc/profile援引(source) /etc/bashrc 文件,读取并执行其中的命令,然后查找并读取执行 /etc/profile.d 目录中以 .sh 结尾的文件。同样的,~/.bash_profile 通常也会 援引(source) ~/.bashrc 文件。/etc/bashrc~/.bashrc 都会进行检查,避免重复 援引(source)

(LCTT 译注:在 Bash 中,脚本会通过 source. 命令来将另外一个脚本引入其中,这个行为称之为 “source”、“sourcing”,但是该行为一直没有公认且常用的翻译方法。经过多番斟酌,我认为可以译做“援引”,理由如下:1、“援引”具有“引用、引入”的意思,符合该行为;2、“援”这个词的发音和“source” 常见的汉语意思“源”同音,便于记忆。以上是我们的愚见,供大家参考讨论。—— 老王,2020/7/19)

一个交互式的 shell,如果不是登录 shell,那么当它第一次被调用的时候,会执行 ~/.bashrc 文件。这是用户在 Fedora 上打开终端时通常会进入的 shell 类型。当 Bash 以非交互模式启动 —— 就像运行脚本时那样 —— 它会寻找 BASH_ENV环境变量。如果找到了,就会展开它的值作为文件名,接着读取并执行该文件。效果跟执行以下命令相同:

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

值得注意的是,不会使用 PATH 环境变量的值来搜索该文件名(LCTT 译注:意即不会检索搜索路径)。

重要的用户点文件

Bash 最广为人知的用户点文件是 ~/.bashrc。通过编辑该文件,可以设置大多数个性化选项。由于我们常常需要设置一些选项,会改动上面提及甚至没有提及的文件,所以大部分自定义选项会成为一个麻烦事。Bash 环境具有很高的可定制性,正是为了适应不同用户的不同需求。

当登录 shell 正常退出时,如果~/.bash_logout/etc/bash_logout存在,它们会被调用。下一幅图展示了 Bash 作为交互式 shell 启动时的过程。例如,当用户从桌面环境打开终端模拟器时,会按照以下顺序进行。

我们已经知道,在不同的启动模式下,Bash 会执行不同的命令,所以很明显,只有几种最需要关注的典型启动模式。分别是非交互、交互式登录 shell,和非交互式、交互式非登录 shell。如果想定义某些全局环境,那么需要将一个具有唯一名称、以 .sh 为后缀的文件(例如 custom.sh)放置在 /etc/profile.d 目录。

对于非交互式非登录启动方式,需要特别注意。在这种模式下,Bash 会检查 BASH_ENV 变量。如果定义了该变量,Bash 会援引它所指向的文件。另外,处理 BASH_ENV 时并不会使用 PATH 变量所存储的值(LCTT 译注:意即不会检索搜索路径),所以它必须包含执行文件的绝对路径。比如说,如果有人希望非交互式执行脚本时,shell 能读取 ~/.bashrc 文件中的设置,那么他可以把类似下面这样的内容放在一个名为 /etc/profile.d/custom.sh 的文件中...

# custom.sh
.
.
.
# 如果使用 Fedora Workstation
BASH_ENV="/home/username/.bashrc"
.
.
.
# 如果使用 Fedora Silverblue Workstation
BASH_ENV="/var/home/username/.bashrc"

export BASH_ENV

上面这份脚本会让每个 shell 脚本在运行之前先执行该用户的 ~/.bashrc

用户一般都会自定义他们的系统环境,以便契合他们自己的工作习惯与偏好。举例来说,用户可以通过别名来实现这种程度的自定义。拥有相同起始参数、需要频繁使用的命令是制作别名的最佳选择。以下展示了一些来自 ~/.bashrc 文件中定义的别名。

# .bashrc
# 执行全局文件
if [ -f /etc/bashrc ];
   then . /etc/bashrc
fi
.
.
.
# 用户别名和函数
alias ls='ls -hF --color=auto'
alias la='ls -ahF --color=auto'

# 让 dir 命令用起来像在 Windows 那样
alias dir='ls --color=auto --format=long'

# 用颜色高亮 grep 结果
alias grep='grep --color=auto'

在系统中,别名是一种自定义各种命令的方法。它能减少击键次数,而且让命令用起来更方便。针对用户级别的别名通常存放在该用户的 ~/.bashrc 文件中。

如果你发现自己经常要去历史中查找曾经执行过的某条命令,那可能需要改改历史设置了。你依然可以在 ~/.bashrc 文件中设置针对用户级别的历史选项。比如说,如习惯同时使用多个终端,那你可能要启用 histappend 选项。某些 Bash 相关的 shell 选项本质上是布尔值(接收 onoff),通常可以用内置命令 shopt 启用或禁用。接收更复杂的值的 Bash 选项(如 HISTTIMEFORMAT),常常通过赋值给环境变量来达到配置目的。以下演示如何以 shell 选项和环境变量定制 Bash。

# 配置 Bash 历史

# 用制表符扩展目录环境变量,并设置 histappend
shopt -s direxpand histappend

# ignoreboth 等同于 ignorespace 和 ignoredup
HISTCONTROL='ignoreboth'

# 控制 `history` 输出中的时间格式
HISTTIMEFORMAT="[%F %T] "

# 无限历史记录
# NB:在新版 Bash 中,任何 < 0 的写法都有效,但是在 CentOS/RHEL 中,只有这样才行得通
HISTSIZE=
HISTFILESIZE=

# 或者对于使用新版 Bash 的人
HISTSIZE=-1
HISTFILESIZE=-1

上面例子中的 direxpand 选项,可以让 Bash 在文件名补全时,用单词展开结果替换目录名。它会改变 readline 编辑缓冲区的内容,所以你所输入的东西已经被补全得到的结果替换了。

HISTCONTROL 变量用于启用或禁用命令历史的某些过滤选项。重复行、以空白打头的行,都能通过该选项将它们从命令历史中过滤掉。引用自 Dusty Mabe,这是我从他那儿得到的技巧:

ignoredup 可以让历史不记录重复条目(如果你反复执行同一条命令)。ignorespace 会忽略前面有空白的条目,当你在设置一个包含敏感信息的环境变量或者执行一条不想被记录进磁盘的命令时,这就很有用。ignoreboth相当于这两条选项的结合体。 Dusty Mabe – Redhat首席软件工程师,2020.6.19

对于命令行重度用户,Bash 有一个 CDPATH 环境变量。如果 CDPATH 包含一系列供 cd 命令搜索的目录,且提供一个相对路径作为第一个参数,那么它会按顺序检查所有列出的目录,寻找匹配的子目录并切换到第一个匹配结果目录。

# .bash_profile

# 设置 CDPATH
CDPATH="/var/home/username/favdir1:/var/home/username/favdir2:/var/home/username/favdir3"

# 也可以写成这样
CDPATH="/:~:/var:~/favdir1:~/favdir2:~/favdir3"

export CDPATH

CDPATH 通常像 PATH 一样的方式进行更新 —— 通过在赋值右侧引用自身来保留原来的值。

# .bash_profile

# 设置 CDPATH
CDPATH="/var/home/username/favdir1:/var/home/username/favdir2:/var/home/username/favdir3"

# 或者写成这样
CDPATH="/:~:/var:~/favdir1:~/favdir2:~/favdir3"

CDPATH="$CDPATH:~/favdir4:~/favdir5"

export CDPATH

PATH 是另一个极其重要的变量。它是系统上的命令的搜索路径。注意,有些应用要求将它们自己的目录加入 PATH 变量,这样才能正常使用。跟 CDPATH 一样,通过在赋值右侧引用原值来追加新值到 PATH 变量。如果你希望将新值前置,只需要把原来的值($PATH)放到列表末尾即可。还有注意的是在 Fedora,这一列值通过冒号分隔(:)。

# .bash_profile

# 添加 PATH 值到 PAHT 环境变量
PATH="$PATH:~/bin:~:/usr/bin:/bin:~/jdk-13.0.2:~/apache-maven-3.6.3"

export PATH

命令提示符是另一个流行的自定义选项。它有七个可定制的参数:

  • PROMPT_COMMAND:如果设置了,会在每一个主提示符($PS1)出现之前执行该值。
  • PROMPT_DIRTRIM:如果设置成大于零的数,则该值用作展开 \w\W 提示符字符串转义符时保留的尾随目录组件数量。删除的字符将替换为省略号。
  • PS0:这个参数的值像 PS1 一样展开,在交互式 shell 读取命令之后、执行命令之前展示。
  • PS1:主提示符字符串。默认值是 \s-\v\$
  • PS2:次提示符字符串。默认是 > 。在显示之前,PS2PS1 那样展开。
  • PS3:这个参数的值用作 select 命令的提示符。如果这个变量没有设置,select 命令会用 #? 作为提示符。
  • PS4:这个参数的值像 PS1 那样展开,如果设置了 -x 选项,这个展开值会在命令行被回显之前作为提示符显示。展开后的值的第一个字符在必要时会复制数次,指示间接层数。默认值是 +

Bash 参考文档 第五版,Bash 版本 5.0 2019 年 5 月

Bash 的这一个方面就可以用整篇文章来讨论。你可以找到许许多多信息和例子。在本文末尾链接的存储库中提供了一些点文件范例,包括提示符重新配置。你可以随意使用该存储库中的例子进行学习和体验。

总结

既然你已经掌握了一些 Bash 的工作原理,那就可以轻松修改你的 Bash 点文件,满足你自己的需求和习惯。美化你的提示符,制作一些别名,这样你的电脑才真的属于你。查看 /etc/profile/etc/bashrc/etc/profile.d/ 这些文件的内容,获得一些启发。

你也可以在这里写一些关于终端模拟器的评论。有很多办法可以将你最喜欢的终端,完全配置成你想要的样子。你或许早就想到了,但是通常可以通过……嗯……用户家目录的点文件实现这个目的。终端模拟器也可以作为登录会话启动,有些人总喜欢用登录环境。你使用终端和电脑的姿势,取决于你如何修改(或不修改)你的点文件。

如果你很好奇自己的命令行处于什么会话状态,使用下面这个脚本来判断一下。

#!/bin/bash

case "$-" in
   (*i*) echo This shell is interactive ;;
   (*) echo This shell is not interactive ;;
esac

把这几行放到一个文件里,加上可执行权限,然后运行,就能看到你当前处于何种类型的 shell。$- 在 Bash 中是一个变量,如果是交互式 shell,它会包含字母 i。此外,你可以直接输出 $- 变量然后检查它的输出中是否含有 i 标记。

$ echo $-

参考信息

可以参考以下资料以获取更多信息和示例。Bash 手册也是一个很好的信息来源。请注意,确保你的本地手册页记录了你当前运行的 Bash 版本的特性,因为在网上找到的信息有时可能太老(过时了)或太新(你的系统还没有安装)。

原文链接:https://zhuanlan.zhihu.com/p/161635671

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 2014网络安全APT攻击专题分析

    1.警惕利用Bash漏洞的IRC-BOT 什么是Bash安全漏洞 继2014年4月的“Openssl心脏流血”漏洞之后,另一个重大互联网威胁于2014年9月24...

    安恒信息
  • 给初学Linux的朋友分享一些心得总结

    很多同学接触linux不多,对linux平台的开发更是一无所知。 而现在的趋势越来越表明,作为一个优秀的软件开发人员,或计算机it行业从业人员,=""

    用户6754675
  • 谈谈Linux的学习方法与学习中应该注意的一些事

    就如同刚才说的,很多同学以前可能连Linux是什么都不知道,对UNIX更是一无所知。 所以我们从最基础的讲起,对于Linux及UNIX的历史我们不做多谈,直接进...

    用户7705674
  • 如何创建/修改远程仓库 + 如何删除远程仓库 + 如何删除远程仓库中的某个文件或文件夹 + 如何使用git将本地仓库连接到多个远程仓库

    首先我们来区分一些概念、术语、名词。不然脑子一锅粥,总是晕!!! 博主对此深有体会!从中学到了没事要多总结、多归类!

    黑泽君
  • 一些APT攻击案例分享

    2014年我们所知的所有网络攻击,实际上还只是冰山一角,未来的网络空间将出现更多错综复杂、有组织性甚至是由敌对国家发起的网络袭击。APT攻击事件目前趋于爆发式增...

    安恒信息
  • 生信服务器入门级基本设置

    前两天拿到了云筏科技提供的一台 4 核 16G 内存,1TB 硬盘,300M 带宽的服务器(看了一下 IP,应该是位于加拿大的服务器)!虽然是国外的服务器,但从...

    史提芬先森
  • 如何在 Linux 上安装友好的交互式 shell:Fish

    Fish 有着很多重要的功能,比如自动建议、语法高亮、可搜索的历史记录(像在 bash 中 CTRL+r)、智能搜索功能、极好的 VGA 颜色支持、基于 web...

    企鹅号小编
  • 黑客最想要的礼物!看完我眼红了 你呢?

    有个黑客朋友(其实在做安全)马上要过生日了,问他想要什么礼物,然后,他丢给了我上面这张图,留言“看着图买”。

    小林C语言
  • 初探Linux

    操作系统(Operating System,OS)是软件的一部分,它是硬件基础上的第一层软件,是硬件和其它软件沟通的桥梁。

    鱼丸葱面
  • vulhub之DC-2

    乌鸦安全的技术文章仅供参考,此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任...

    乌鸦安全
  • 如何学习Linux

    在现在的生活,生产,研究等领域,Linux已经无所不在,从我们使用的手机,车载设备,到服务器,桌面电脑等,Linux已经成为这个世界方方面面的基石。尤其对于参与...

    马哥教育小师哥
  • 北京两日求职之旅有感

    版权声明:本文为耕耘实录原创文章,各大自媒体平台同步更新。欢迎转载,转载请注明出处,谢谢

    耕耘实录
  • 新手如何学习(入坑) Linux

    总会看到一些新手入坑 Linux 以后,连填坑的方向都找不到。所以蛋疼得紧啊,我就写个入坑 Linux 的介绍吧。

    明月云服务
  • 关于CentOS6平台上PM2安装失败的解决方案

    因此,安装PM2失败的原因在于未满足环境依赖,即Node.js和npm版本较低,不满足安装PM2的基本要求;而安装Nodejs时,将会自动安装npm,因为我们只...

    用户1456517
  • 初学机器学习的你,是否掌握了这样的Linux技巧?

    选自alexpetralia 机器之心编译 Linux 因其稳定性获得了不少开发者的青睐,同时也成为大多数服务器的操作系统,对于机器学习开发者来说,使用 Mac...

    机器之心
  • 宝塔Linux面板安装教程 - 7月10日更新 - 6.9.7正式版

    复制代码 以上节点无法使用的情况下,请使用下面的备用节点: 备用节点【广东】:(宝塔推荐使用充值0.08元即可使用的尊云zun.com云...

    拓荒者
  • 听说 90% 的人都在 win10 下使用 ubuntu 子系统了!

    最近,遇到很多Python第三方库不支持Windows系统或则安装很繁琐要不就是要安装vc++环境,都比较麻烦,对于开发者而言,Mac真的是个不错的选择,Lin...

    小Gy
  • Linux之《荒岛余生》(一)准备篇

    xin片之争,已经暴露了中国xin的问题,我等码农束手无策;而在操作系统方面,成果也是乏善可陈;现如今酷炫的Web监控工具,让很多研发丧失了真正处理问题的能力。...

    xjjdog
  • 3个命令行游戏--乐学乐玩Bash【Linux-Command line】

    学习是艰苦的工作,没有人喜欢工作。这意味着无论学习Bash多么容易,它对你来说仍然像件差事。当然,除非你通过游戏学习。

    QRosie

扫码关注云+社区

领取腾讯云代金券