GUN/Bash 系列(八)快捷键总结
下面总结的是 GNU/Bash 中部分最实用的命令名称及默认情况下它们关联的快捷键。更多快捷键请参考 GNU/Bash 文档的 Readline 库。
下面总结的是 GNU/Bash 中部分最实用的命令名称及默认情况下它们关联的快捷键。更多快捷键请参考 GNU/Bash 文档的 Readline 库。
搭好博客后,在权威域名服务商 GoDaddy 注册了一个新域名使用。当配置无 www 前缀域名时,却遇到了一些配置问题。
Q1 参加了一场 Docker 技术分享后,发现了 Docker 这个好东西,回头动手安装,打算跑起来体验一番,却遇到了一些蛋疼的问题。
在使用交互式 Bash 时,一个配置得当的命令提示符可以为用户带来不少便利,本文讲解如何配置命令提示符。
命令提示符涉及到以下两个环境变量:
| 环境变量 | 描述 |
|---|---|
PS1 |
主提示符,Bash 会在准备好读入一条命令时显示,默认值 \s-\v\$ |
PS2 |
次提示符,Bash 会在需要更多的输入来完成一条命令时显示,默认值 > |
Bash 允许通过插入一些反斜杠转义的特殊字符来定制这些提示符,常用的转义字符如下:
| 转义字符 | 描述 |
|---|---|
\h |
主机名,第一个 . 之前的部分 |
\H |
主机名 |
\j |
shell 当前管理的作业数量 |
\l |
shell 的终端设备名的基本部分 |
\n |
新行符 |
\r |
回车 |
\s |
shell 的名称, $0 的基本部分 (最后一个斜杠后面的部分) |
\u |
当前用户的用户名 |
\v |
bash 的版本 (例如,4.3) |
\w |
当前工作目录 |
\W |
当前工作目录的基本部分 |
\! |
此命令的历史编号 |
\# |
此命令的命令编号 |
\$ |
如果有效 UID 为 0,则显示 #, 否则 $ |
\\ |
一个反斜杠 |
除此之外,还有一些不太常用的日期转义字符:
| 转义字符 | 描述 |
|---|---|
\d |
当前日期,格式是 “星期 月份 日” (例如,”Tue May 26”) |
\D{format} |
自定义日期格式,花括号是必需的 |
\t |
当前时间,采用 24 小时制的 HH:MM:SS 格式 |
\T |
当前时间,采用 12 小时制的 HH:MM:SS 格式 |
\@ |
当前时间,采用 12 小时制上午/下午 am/pm 格式 |
\A |
当前时间,采用 24 小时制上午/下午格式 |
由于 PS1 默认设置的 \s-\v\$ 实在是太废毫无信息量可言,显示如下:
1 | bash-4.3$ |
因此可以通过修改 ~/.bash_profile 文件来定制自己的命令提示符。例如,使用 CentOS 默认设置的 [\u@\h \W]\$:
1 | $ vim ~/.bash_profile |
定制后,能够知道当前用户、主机名、工作目录:
1 | [root@BGP-BJ-C-5HL ~]$ |
http://www.gnu.org/software/bash/manual/bashref.html#Controlling-the-Prompt

命令行的扩展是在拆分成词之后进行的。共有七种类型的扩展:
常用的四种如下
用于偷懒,例如:
1 | x{a,b,cd}y |
扩展为:
1 | xay xby xcdy |
再例如:
1 | mkdir /usr/local/src/bash/{old,new,dist} |
扩展为:
1 | mkdir /usr/local/src/bash/old |
1 | ${parameter} |
1 | $(( expression )) |
命令替换允许命令的输出替换命令本身。当命令被以下特殊字符包括时,将发生命令替换:
1 | $(command) |
或
1 | `command` |
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Expansions
GUN/Bash 提供了一些内建命令 (BUILTIN COMMANDS),用于在命令行上方便使用:
echo 显示一行文本或变量
unset 取消变量
set 查看所有变量(环境变量&用户变量)
env 查看所有环境变量(格式好看些)
export
export 命令将局部变量转为环境变量,但是用户注销时值将丢失;export 命令,相当于每次登录时系统都帮用户 export 一下所需环境变量;source 或 .
exit 注销)declare 或 typeset
-a 定义数组类型-i 定义整数类型-x 将用户变量转成环境变量(与 export 一样)+x 将环境变量降为用户变量-r 定义 readonly 类型read 读取来自键盘输入的变量
-p 后接提示符-t 后接等待“秒数”test
-e 该文件名是否存在(exist)-s 该文件大小是否非 0-z 是否为空字符串(zero)-f 是否为文件(file)-d 是否为目录(directory)-b 是否为块特殊文件(block)-L 是否为连接文件(link)-r -w -x 是否可读、可写、可执行-a -o ! 且、或、非-eq -ne -gt -lt -ge -le (判断2个整数)相等、不等、大于、小于、大于等于、小于等于[]
[] 的使用方法与 test 命令几乎一模一样,只是中括号常用于条件判断式 if…then…fi'' 或双引号 "" 括起来sh 以 sh 方式执行,至少需要 r 权限;若以绝对路径方式执行,则需要 r 与 x 权限
-n 不执行 script,仅验证语法。若语法无误,则不显示任何信息。(貌似仅能验证关键字错误?)-v 在执行 script 前,先将 script 的内容输出到屏幕上-x 将 script 执行过程逐步输出到屏幕上Bash 是一个多任务的 CLI ,有以下作业控制(Job Control)相关的命令:
| 命令 | 描述 |
|---|---|
jobs |
显示(当前会话中的)后台作业表 |
fg |
将后台作业调到前台执行(前台运行作业) |
bg |
继续执行指定的后台作业(后台运行作业) |
Ctrl+Z |
暂停/挂起目前的命令,转入后台运行。通过在命令后追加一个&,可以将该命令转入后台运行 |
Ctrl+C |
终止目前的命令 |

http://www.gnu.org/software/bash/manual/bashref.html#Shell-Builtin-Commands

即单个命令。


pipeline(管道)是一个或多个命令的序列,用字符 | 分隔。管道的命令格式如下:
1 | command [ | command2 ... ] |
管道的特点如下:
|管道的处理流程如下图:

| 文件描述符 | 名称 | 描述 |
|---|---|---|
0 |
stdin |
标准输入(Standard input) |
1 |
stdout |
标准输出(Standard output) |
2 |
stderr |
标准错误输出(Standard error) |

| 操作符 | 描述 |
|---|---|
< |
重定向输入(Redirecting Input) |
> |
重定向输出(Redirecting Output),与 1> 等价 |
>> |
追加到重定向输出(Appending Redirected Output) |
2> |
重定向错误输出(Redirecting Error) |
2>> |
追加到重定向错误输出(Appending Redirected Error) |
&> |
重定向标准输出和标准错误输出(Redirecting Standard Output and Standard Error)。 推荐使用,它与 >word 2>&1 在语义上等价 |
>& |
同上,但不推荐使用 |
2>&1 |
将标准错误输出重定向到标准输出 |

在命令执行前,它的输入和输出可能被 redirected (重定向),该功能可以用于如下场景:
2> /dev/null 将它丢掉;/etc/crontab)的运行结果,需要存下来时;例子:
快速创建带内容的文件:
1 | $ echo "hello world" > /tmp/file |
将 stdout 和 stderr 都重定向到本地日志文件:
1 | java -jar app.jar >/tmp/stdout.log 2>&1 |
将 stdout 和 stderr 都丢弃(等价操作):
1 | java -jar app.jar >/dev/null 2>&1 |
list(序列)是一个或多个管道,用操作符 ;、&、&&、|| 分隔的序列, 并且可以选择用 ;、&、<newline> 新行符结束。
| 操作符 | 例子 | 描述 |
|---|---|---|
&& |
command1 && command2 | 一个 AND 序列。command2 只有在 command1 返回 0 时才被执行 |
|| |
command1 || command2 | 一个 OR 序列。command2 只有在 command1 返回非 0 状态时才被执行 |
; |
command1; command2 | 结束一个序列。不考虑命令的退出状态,连续执行命令 |
<newline> |
command<newline> | 结束一个序列 |
& |
command1 & | 如果一个命令是由 & 结束的, shell 将在后台的子 shell 中执行这个命令 |
&& 和 || 优先级相同, ; 和 & 优先级相同。在某些情况下,很多命令我想要一次输入去运行,有两种方法:
例如,一串无人值守源代码形式安装的命令如下:
1 | $ ./configure && make && make install |
compound command(复合命令)是如下情况之一:
(list){ list; }((expression))[[ expression ]]if list; then list; [ elif list; then list; ] ... [ else list; ] fi
select name [ in word ] ; do list ; donecase word in [ [(] pattern [ | pattern ] select in 通常和 case in 一起使用,在用户输入不同的编号时可以做出不同的反应,见:https://blog.csdn.net/yrx420909/article/details/104308041
while list; do list; done
until list; do list; done
for name [ in word ] ; do list ; done
1 | #!/bin/bash |
for (( expr1 ; expr2 ; expr3 )) ; do list ; done

https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Arrays
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Commands

引用用于:
三种引用机制:
| 引用符 | 描述 |
|---|---|
转义字符 \ |
保留其后下一个字符的字面意义 |
单引号 '' |
保留引用中所有字符的字面意义 |
双引号 "" |
保留引用中所有字符的字面意义,例外的情况是 $, `, 和 \ |
单引号与双引号的使用区别:

注意,反引号 ` 与单引号 '' 和双引号 "" 作用不同,是用于命令替换(Command Substitution),详见《Shell 常用扩展总结》。
以 # 起始的词使得这个词和所有同一行上所有剩余的字符都被忽略。
参数(Parameter)是存储值的实体。它可以是以下三类:


变量,即用名称(name)表示的参数,其具有值(value)以及零或多个属性(attributes)。
通过 $name 引用,在双引号 "" 中可以被引用。
通过以下语句为变量赋值:name=[value]。如果变量未赋值,默认值为 null 字符串。
通过内建命令 unset 为取消变量。
通过内建命令 declare 为变量分配属性(attributes)。
所有值都接受以下扩展:
$n:$1 表示第一个参数,$2 表示第二个参数,以此类推。
$0:表示脚本文件名
$#:表示命令行参数的个数
$?:前一个命令或函数的返回码,0 为成功,非 0 为错误/失败
$*:以”参数1 参数2 … “ 的形式保存所有参数
$@:以”参数1” “参数2” … 的形式保存所有参数
$$:本程序的 PID(进程 ID 号)
$!:最近执行的后台(即异步)命令的 PID

https://www.gnu.org/software/bash/manual/html_node/Quoting.html
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameters
了解完什么是 Shell,有哪些 Shell 类型之后,本文开始主要关注 Bash Shell。
/etc/passwd 文件,在这个文件里包含了用户名、密码和该用户的登录 shell,如 /bin/bash 。 /bin/login 在子进程里用 execve 调用了 /bin/bash 。echo 命令时,我们一般不会输入 /bin/echo ,而仅仅是输入 echo 。那为什么这样 bash 也能够找到 /bin/echo 呢?原因是 Linux 操作系统支持这样一种策略:shell 的一个环境变量 PATH 里头存放了程序的一些路径,当 shell 执行程序时会去这些目录下查找。which 作为 shell(这里特指 bash )的一个内置命令,如果用户输入的命令是磁盘上的某个程序,它会返回这个文件的全路径。Bash 如何执行它的启动文件?交互式 shell(interactive shell)下需要区分两种情况:
在下列情况下,我们可以获得一个 login shell:
ssh 登录。这种情况下获得的 login shell 是一个交互式 shell。--login 选项调用 bash,可以获得一个交互式 login shell。--login 选项调用 bash(比如在 shell 脚本第一行做如下指定:#!/bin/bash --login),此时得到一个非交互式的 login shell。su - 切换到指定用户时,获得此用户的 login shell。如果不使用 -,则获得 non-login shell。login shell 与 non-login shell 的主要区别在于它们启动时会读取不同的配置文件,从而导致环境不一样。login shell 启动时:
首先读取全局配置:/etc/profile
然后依次查找以下三个文件,读取第一个找到且可读的文件:
~/.bash_profile~/.bash_login~/.profile退出时,读取:~/.bash_logout
交互式的 non-login shell 启动时,会读取:
~/.bashrc通常我们要定制一些配置时(例如 alias 别名),会将配置写在 ~/.bashrc 中,然后在 ~/.bash_profile 中读取 ~/.bashrc,这样可以保证 login shell 和 non-login shell 得到相同的配置:
1 | test -f ~/.bashrc && . ~/.bashrc |
至于 /etc/profile 就不要轻易去改啦,毕竟会影响系统全局的配置。
当 Bash 以非交互的方式(non-interactive shell)启动时,例如在运行一个 shell 脚本时,它会查找环境变量 BASH_ENV,如果存在则将它的值展开,使用展开的值作为一个文件的名称,读取并执行。 Bash 运作的过程就如同执行了下列命令:
1 | if [ -n "$BASH_ENV" ]; then |
其它情况:
Aliases are not expanded when the shell is not interactive.
Functions are executed in the context of the current shell; no new process is created to interpret them (contrast this with the execution of a shell script).