你不得不知道的Bash知识点

bash是所有命令行模式与未来主机管理的重要基础。学习《鸟哥的LINUX私房菜》一书,由于这书太厚,携带不方便,因此我个人觉得有用的知识点记录到博客中,以便于以后用到的时候查阅。

认识SHELL

计算机硬件是由内核统一管理的,而用户则是通过shell来和内核沟通,以让内核完成我们想要实现的任务。

shell是壳, 它是一个软件, 它提供了一个用户操作系统的一个接口, 通过shell我们可以调用其他软件,比如chmod 、chown、firefox、man 等, 它可以调用内核来工作. shell其实就是一个接口;狭义的shell 指的是命令行界面,比如我们的bash;广义的shell 则包括图形界面的软件,因为其实图形界面也可以调用系统内核。

系统合法shell与/etc/shells功能

以CentOS 7.x为例,通过命令cat /etc/shells查看可以使用的shell有哪些?如:

1
2
3
4
5
[root@node01 etc]# cat shells
/bin/sh # 已被/bin/bash所替换
/bin/bash # linux默认的shell
/bin/tcsh # 整合C Shell,提供更多功能
/bin/csh # 已经被/bin/bash所替换

为什么系统上合法的shell要写入/etc/shells这个文件中?

答:因为系统某些服务在运行过程中,会去检查用户能够使用的shells,而这些shell的查询就是借由/etc/shells这个文件。

如何知道用户默认会取得哪一个shell?

答:当登陆时,系统会默认分配一个shell让其工作,在/etc/passwd文件中查看。如:

1
2
3
4
5
6
7
8
[root@yun19 etc]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

Bash shell的功能

bash是GNU计划中重要的工具软件之一,目前也是Linux发行版的标准shell。bash主要兼容于sh,并且依据一些用户需求而加强的shell版本。

bash的优点如下:

  • 历史命令

    历史命令记录在~/.bash_history文件中。需要注意的是,该文件记录的是前一次登录以前所执行过的命令,而至于这一次登录所执行的命令都被缓存在内存中,当你成功的注销系统后,该命令才会记录到.bash_history当中。

  • 命令与文件补全功能

  • 命令别名设置

  • 任务管理、前台、后台控制

  • 程序化脚本

  • 通配符

查询命令是否为bash shell的内置命令:type

1
type [-tpa] name
  • 无参数:显示name是外部命令还是bash内置命令

  • -t: 该参数将name以下字眼显示它的意义:

    • file: 表示外部命令
    • alias:表示为命令别名所设置的名称
    • builtin:表示内置命令
  • -p:当name为外部命令时,才显示完整文件名

  • -a:由PATH变量定义的路径中,将所有含name的命令都列出来,包含alias

快速编辑按钮

组合键 功能
[ Ctrl ] + u 从光标处向前删除命令行
[ Ctrl ] + k 从光标处向后删除命令行
[ Ctrl ] + a 光标移动至命令行最前面
[ Ctrl ] + e 光标移动至命令行最后面

shell的变量功能

什么是变量

变量就是以一组文字或符号等,来取代一些设定或者是一串保留的数据。

变量的获取与设置:echo

在bash中,当一个变量名称尚未被设定时,预设的内容是【空】的。

1
2
变量名=值
echo $变量名 或 echo ${变量名}

变量的设定规则

  1. 变量与变量内容以一个等号【=】来连接;

  2. 等号两边不能有空格符;

  3. 变量名只能是英文字母与数字,且不能以数字开头;

  4. 变量值若有空格符可使用双引号【“】或单引号【‘】括起来,但

    • 双引号内的特殊字符可以保有原来的特性;

    • 单引号内得特殊字符则仅为一般字符(纯文本);

  5. 可用转义字符【\】将特殊符号变为一般字符;

  6. 在一串指令的执行中,还需要借由其他额外的指令所提供的信息时,可以使用反单引号【`指令`】或【$(指令)】;

  7. 若该变量为扩增变量内容时,则可用”$变量名称“或${变量}累加内容,如:

    1
    2
    PATH="$PATH":/home/bin
    PATH=${PATH}:/home/bin
  8. 若该变量需要在其他子程序执行,则需要以export来使变量变成环境变量;

    1
    export PATH
  9. 通常大写字符为系统默认变量,自行设定变量可以使用小写字符;

  10. 取消变量的方法:unset

    1
    unset myname

环境变量

查看环境变量

1
env

如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
## 主机名
HOSTNAME=node19
## 终端机使用的环境类型
TERM=xterm
## 当前环境下使用的shell程序
SHELL=/bin/bash
## 历史记录条数
HISTSIZE=1000
## 当前用户
USER=root
## 一些颜色显示
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;...此处省略...
## 用户所取用的mailbox位置
MAIL=/var/spool/mail/root
## 执行文件搜寻的路径,目录与目录之间以冒号【:】分隔,按照顺序查询
PATH=/usr/local/jdk/bin:/usr/local/mysql/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/mysql/bin:/root/bin
## 当前用户所在的工作目录
PWD=/root
## JDK安装目录
JAVA_HOME=/usr/local/jdk
## 语系
LANG=en_US.UTF-8
## 用户家目录
HOME=/root
...

基本上,在Linux预设的情况中,使用{大写的字母}来设定的变量一般为系统内定需要的变量

几个重要的系统变量

  • PS1(提示字符设置)

    1
    2
    3
    4
    5
    # 查看PS1变量
    [root@node01 ~]# echo ${PS1}
    [\u@\h \W]\$
    # 设置PS1变量
    [root@node01 ~]# PS1='[\u@\h \W]\$'^C

    符号说明:

    符号 说明 符号 说明
    \d 【星期 月 日】的日期格式 \u 当前用户账户名称
    \H 完整主机名 \v BASH的版本信息
    \h 主机名小数点前的名字 \w 完整工作目录名称
    \t 【HH:MM:SS】24小时格式 \W basename函数取得工作目录名称
    \T 【HH:MM:SS】12小时格式 \# 执行的第几个命令
    \A 【HH:MM】24小时格式 \$ 提示字符;如root时为#,否则为$
    @ 【am/pm】12小时格式
  • $(表示当前SHELL的进程号PID)

    1
    echo $$
  • (关于上一个命令执行的返回值)

    执行某个命令后,若执行成功则返回0;若执行不成功则返回一个非零值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [root@node01 ~]# echo $SHELL
    /bin/bash
    [root@node01 ~]# echo $?
    0
    [root@node01 ~]# 12name=qixige
    bash: 12name=qixige: command not found...
    [root@node01 ~]# echo $?
    127
    [root@node01 ~]#
  • OSTYPE, HOSTTYPE, MACHTYPE(主机硬件与内核等级)

export将自定义变量转换为环境变量

子进程仅会继承父进程的环境变量,但时不会继承父进程的自定义变量;如果想要让子进程继承父进程变量,那么就执行:

1
export 变量名称

影响显示结果的语系变量(locale)

  • 如何查看linux支持多少语系?

    1
    locale -a
  • 当需要设置语系的时候,只需要设置LANG或是LC_ALL;其它语系变量都会被这两个变量替换;

  • 语系文件都放置在:/usr/lib/locale中;

  • 整体系统默认语系设置

    1
    vim /etc/locale.conf

变量的有效范围

环境变量可以被子进程引用,自定义变量不能被子进程引用;被export后的变量被称之为环境变量。

变量键盘读取、数组与声明:read、array、declare

read [-pt] 变量

  • -p:接提示字符
  • -t:接等待的秒数
1
read -p "Please input your name: " -t 30 name

declare,typeset:声明变量的类型

语法:declare -[aixr] 变量

  • -a:将变量定义为数组类型
  • -i:定义为整数类型
  • -x:和export一样,将变量变为环境变量
  • -r:将变量设置为只读,不能被更改,不能unset(设置后,注销再登陆才能恢复)

注意:

  • 变量类型默认为字符串;
  • 在bash环境中的数值运算,仅能达到整数形态。如1/3=0

数组(array)

语法:var[index]=content

1
2
3
4
5
[root@node01 ~]#array[1]="qixige"
[root@node01 ~]#array[2]="panglaoda"
[root@node01 ~]#array[3]="xiaogaogao"
[root@node01 ~]#echo "${array[1]},${array[2]},${array[3]}"
qixige,panglaoda,xiaogaogao

与文件系统及程序的限制关系:ulimit

命令别名和历史命令

命令别名设置:alias、unalias

语法:【别名】=‘命令 选项…’

历史命令:history

1
2
3
4
5
6
7
8
# 列出最近的n条命令行表
history n
# 将目前shell中的所有history内容全部删除
history -c
# 执行第几条命令
!number
# 执行上一个命令
!!

Bash shell的操作环境

路径与命令查找顺序

相对/绝对路径执行命令 > alias找到该命令执行 > bash内置命令 > 通过$PATH变量的顺序查找到第一个执行

查询命令执行顺序:如type -a ls

1
type -a 命令

bash环境配置文件

login 与 non-login shell

login shell:取得bash时需要完整的登录流程;

non-login shell:取得bash的方法不需要重复登录的操作

一般来说,login shell只会读取两个配置文件:

  • /etc/profile:系统整体设置,最好不要修改
  • ~/.bash_profile或 ~/.bash_login 或 ~/.profile:属于用户个人设置,需要添加自己的数据,就写入这里

/etc/profile

系统环境配置,login shell才会读。该配置文件利用用户标识符(UID)来决定很多重要的变量数据,而且也是每个用户登录取得bash时一定会读取的配置文件。

/etc/profile回去调用外部的配置文件,下面文件会依序被调用:

  1. /etc/profile.d/*.sh

    该目录下的文件规范了bash操作界面的颜色、语系、ll与ls命令的命令别名、vi的命令别名、which的命令别名等。用户需要具有r权限。

  2. /etc/locale.conf

    /etc/profile.s/lang.sh文件调用,也是决定bash默认使用何种语系的配置文件。

  3. /usr/share/bash-completion/completions/*

    /etc/profile.d/bash_completion.sh文件加载

总之,bash的login shell情况下所读取的整体环境配置文件其实只有/etc/profile,但是/etc/profile还会调出其它的配置文件。

~/.bash_profile

用户个人配置文件,只有login shell才会读;bash环境中读取的个人偏好配置文件主要有三个,依序为:

  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile

bash的login shell设置只会读取上面三个文件的其中一个,而读取顺序则是依照上面的顺序。

source

读入环境配置文件的命令。

为什么需要source的原因?

答:由于/etc/profile~/.bash_profile都是在取得login shell的时候才会读取的配置文件。

1
2
3
# source 和 小数点(.) 等价
source ~/.bashrc
. ~/.bashrc

~/.bashrc

当取得non-login shell时,该bash配置文件仅会读取~/.bashrc

问题:CentOS7.x中,如果bash的提示符变成如下样子

1
-bash-4.2$

这是因为没有调用/etc/bashrc来规范PS1变量,该情况不影响使用

解决办法:复制/etc/skel/.bashrc到根目录,再自定义想要的内容,并是使用source去调用~/.bashrc即可

其它相关配置文件

  • /etc/man_db.conf:规范了使用man的时候,man page的路径到哪里去寻找;
  • ~/.bash_history:历史命令
  • ~/.bash_logout:记录【当注销bash后,系统再帮我做完什么操作后才离开】

终端的环境设置:stty、set

1
2
stty [-a]
# -a: 将目前所有的参数列出来

例如:其中出现 ^表示[Ctrl]那个按键的意思

1
2
3
4
[root@yun19 skel]#stty -a
speed 38400 baud; rows 59; columns 127; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S;
susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;

解释几个重要关键词的意义:

关键词 意义
intr 发送interrupt的信号给目前正在run的程序(终止)
quit 发送quit信号给正在run的程序
erase 向后删除字符
kill 删除在目前命令行上的所有文字
eof end of file; 结束输入
start 在某个程序停止后,重新启动它的output
stop 停止目前屏幕的输出
susp 送出一个terminal stop的信号给正在运行的程序

bash的默认组合键

组合键 执行结果
Ctrl + C 终止目前命令
Ctrl + D 输入结束(EOF)
Ctrl + M 回车
Ctrl + S 暂停屏幕的输出
Ctrl + Q 恢复屏幕的输出
Ctrl + U 在提示字符下,将整列命令删除
Ctrl + Z 暂停目前的命令

重定向

数据流重定向就是将某个命令执行后应该要出现在屏幕上的数据,给他传输到其它的地方。

什么是数据流重定向

standard output 与 standard error output

标准输出指的是命令执行所返回的正确信息,而标准错误输出可理解为命令执行失败后,所返回的错误信息。

重定向传送所用特殊字符:

  • 标准输入(stdin):代码为0,使用 < 或 <<
  • 标准输出(stdout):代码为1,使用 > 或 >>
  • 标准错误输出(stderr):代码为2,使用 2> 或 2>>

使用 > 或 >> 的区别:>是以覆盖的方式输出数据到指定文件中;>>是以累加的方式输出数据到指定的文件中;输入同理。

/dev/null垃圾桶黑洞设备与特殊写法

dev/null:可以吃掉任何导向这个设备的信息。

如何将正确与错误数据通通写入同一个文件中?

答: 使用特殊写法: 2>&1$>

1
2
3
find /home -name .bashrc > list 2>$1
# 或者
find /home -name .bashrc $> list

standard input:< 与 <<

将原本需要由键盘输入的数据,改由文件内容来替换。

命令执行的判断依据:; 、&&、||

cmd; cmd (不考虑命令相关性的连续命令执行)

在命令与命令中间利用分号(;)来隔开。

$?(命令返回值) 与 ** 或||

命令执行情况 说明
cmd1 && cmd2 1. 若cmd1执行完毕且正确执行($? = 0),则开始执行cmd2
2. 若cmd1执行完毕且为错误($? != 0),则cmd2不执行
cmd1 || cmd2 1. 若cmd1执行完毕且正确执行($? = 0),则cmd2不执行
2. 若cmd1执行完毕且为错误($? != 0),则开始执行cmd2

管道命令

  • 管道命令使用的是 【|】这个界定符号;
  • 管道命令【|】仅会处理标准输出,对于标准错误会予以忽略;
  • 管道命令必须要能够接受来自前一个命令的数据成为标准输入继续处理才行

选取命令:cut、grep

cut

将一段信息的某一小段给它【切】出来;处理信息是以【行】为单位。

1
2
3
4
# 用于特定分隔字符; fields:表示根据分隔符划分,取出第几段
cut -d '分隔字符' -f fields
# 用于整齐排列的信息,字符区间:如12-20;12-
cut -c 字符区间

注意:cut在处理多空格相连的数据时,可能会比较吃力一点,所以某些时刻可能会使用awk来替换。

grep

分析一行信息,若当中有需要的信息,则将改行显示出来。

1
grep [-acinv] [--color=auto] '查找字符' filename
  • -a:将二进制文件以文本文件形式查找
  • -c:计算找到 ‘查找字符’ 的次数
  • -i:忽略大小写
  • -n:输出行号
  • -v:反向选择

排序命令:sort、wc、uniq

sort

排序前,建议使用LANG=C让语系统一,数据排序比较好一些。详情sort --help

1
sort [-fbMnrtuk] [file or stdin]

wc

文件内容计算工具,计算文件内的行数、字数、字符数

1
2
# -l:仅列出行数	-w:仅列出多少字	-m:多少字符
wc [-lwm]

uniq

去除重复行。

1
2
# -i:忽略大小写; -c:进行计数
uniq [-ic]

字符转换命令:tr、col、join、paste、expand

tr

用来删除一段信息当中的文字,或是进行文字信息的替换。

1
2
# -d:删除信息当中SET1字符	-s:替换掉重复的字符
tr [-ds] SET1...

col

用来简单地处理【tab】按键替换成空格键。

1
2
# -x:将tab键转换成对等的空格键; cat -A 可以显示出所有特殊按键。
col [-xb]

join

两个文件当中,有相同数据的那一行,才将它加在一起。

1
join [-ti12] file1 file2

注意:在使用join之前,所需要处理的文件应该要事先经过排序处理。

paste

直接将两行贴在一起,且中间以【tab】键隔开。

1
2
# -d:后面接分隔符,默认【tab】
paste [-d] file1 file2

expand

将【tab】按键转换成空格键。

1
2
# -t:后面接数字,表示使用几个空格,默认8个空格键
expand [-t] file

划分命令:split

将一个大文件,依据文件大小或行数来划分成一个个的小文件。

1
2
3
# -b:接欲划分的文件大小,可加单位,如b、k、m等		-l:以行数来划分
# PREFIX:前缀字符,划分文件前缀文字
split [-bl] file PREFIX

参考资料

《鸟哥的LINUX私房菜》

硬件 内核 操作系统 shell 的关系

-------------本文结束感谢您的阅读-------------

本文标题:你不得不知道的Bash知识点

文章作者:Mr.wj

发布时间:2019年12月24日 - 21:41

最后更新:2019年12月24日 - 21:48

原始链接:https://www.wjqixige.cn/2019/12/24/你不得不知道的Bash知识点/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Mr.wj wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!