11.认识与学习bash
11.1 认识bash这个shell
管理整个计算机硬件的其实是操作系统的核心 (kernel),这个核心是需要被保护的! 所以我们一般使用者就只能透过 shell 来跟核心沟通,以让核心达到我们所想要达到的工作。
11.1.1 硬件、内核与shell关系
![](https://img-blog.csdn.net/20181018190054751?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE2Mzk5OTkx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
11.1.2 为何要学习命令行界面的shell
-
文字接口的 shell :大家都一样!几乎各家 distributions 使用的 bash 都是一样的!如此一来, 你就能够轻轻松松的转换不同的 distributions ,就像武侠小说里面提到的『一法通、万法通!』
-
远程管理:文字接口就是比较快!Linux 的管理常常需要透过远程联机,而联机时文字接口的传输速度一定比较快, 而且,较不容易出现断线或者是信息外流的问题,因此,shell 真的是得学习的一项工具。
-
Linux 的任督二脉: shell 是也!
11.1.3 系统的合法shell和/etc/shells功能
早年的unix发展版本众多,所有shell依据发展版本不同,发展出多个版本。例如常用的bourne shell,sun里默认的c shell,商业上常 用 的k shell,还有TCSH等,每一种 Shell 都各有其特点。至于 Linux 使用的这一种版本就称为『 Bourne Again SHell (简称 bash) 』,这个 Shell 是 Bourne Shell 的增强版本,也是基准于 GNU 的架构下发展出来的。
那么目前我们的 Linux (以 CentOS 7.x 为例) 有多少我们可以使用的 shells 呢? 你可以检查一下/etc/shells 这个文件,至少就有底下这几个可以用的 shells:
- /bin/sh (已经被/bin/bash所取代)
- /bin/bash (linux 默认的shell)
- /bin/ksh (kornshell 由AT&T Bell lab 发展出来,兼容bash)
- /bin/tash :整合c shell,提供更多功能
- /bin/csh : 已经被/bin/tash 取代
- /bin/zsh : 基于ksh发展出来,功能更加强大的shell
虽然各家 shell 的功能都差不多,但是在某些语法的下达方面则有所不同,因此建议你还是得要选择某一种 shell 来熟悉一下较佳。 Linux 预设就是使用 bash ,所以最初你只要学会 bash 就非常了不起了!
11.1.4 bash shell的功能
bash shell的优点:
- 命令记忆功能 (history) :我只要在指令列按『上下键』就可以找到前/后一个输入的指令!而在很多 distribution 里头,默认的指令记忆功能可以到达 1000 个!也就是说,你曾经下达过的指令几乎都被记录下来了。这么多的指令记录在哪里:记录在你的家目录内的的 .bash_history文件夹中,~/.bash_history 。最大的好处就是可以『查询曾经做过的举动!』。~/.bash_history 记录的是前一次登入以前所执行过的指令, 而至于这一次登入所执行的指令都被暂存在内存,当你成功的注销系统后,该指令记忆才会记录到 .bash_history 当中!
- 命令与文件补全功能 ([Tab] 按键)
- 命令别名设置功能 (alias)你可以在指令列输入 alias 就可以知道目前的命令别名有哪些了!也可以直接下达命令来设定别名: $ alias lm='ls -al'
- 作业控制、前台、后台控制,(job controll 、 foreground 、background):使用前、背景的控制可以让工作进行的更为顺利!
至于工作控制(jobs)的用途则更广, 可以让我们随时将工作丢到背景中执行!而不怕不小心使用了[Ctrl] + c 来停掉该程序! - 程序化脚本: (shell scripts)
- 通配符( wildcard):除了完整的字符串之外, bash 还支持许多的通配符来帮助用户查询与指令下达。 举例来说,想要知道 /usr/bin 底下有多少以 X 为开头的文件吗?使用:『 ls -l /usr/bin/X* 』
11.1.5 bash的内置命令type
如何知道一个命令是来自于外部 还是内置的bash命令
语法:
>type [-tpa] name
不加任何参数时,type会显示出name是内部命令 还是外部命令。
-t:加入-t时,type 会将以下字段显示出来,
file:表示为外部命令
alias:表示该命令为命令别名所设置的名称
builtin:表示该命名为bash内置的命令;
-p:如果后面接的name为外部命令时,才会显示出完整的文件名
-a:会由path定义的路径中,将所有含name的命令都列出来,包含alias;
范例
范例一:查询一下 ls 这个指令是否为 bash 内建?
[dmtsai@study ~]$ type ls
ls is aliased to `ls --color=auto' <==未加任何参数,列出 ls 的最主要使用情况
[dmtsai@study ~]$ type -t ls
alias <==仅列出 ls 执行时的依据
[dmtsai@study ~]$ type -a ls
ls is aliased to `ls --color=auto' <==最先使用 aliase
ls is /usr/bin/ls <==还有找到外部指令在 /bin/ls
范例二:那么 cd 呢?
[dmtsai@study ~]$ type cd
cd is a shell builtin <==看到了吗? cd 是 shell 内建指令
11.1.6 命令的执行
11.2 shell的变量功能
11.2.1 什么是变量
变量的可变性与方便性
影响bash环境操作的变量
脚本程序设计的的好帮手
11.2.2 变量的显示与设置: echo,unset
变数的取用: echo
变量在被取用时,前面必须要加上钱字号『 $ 』才行
范例
[dmtsai@study ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
[dmtsai@study ~]$ echo ${PATH} # 近年来,鸟哥比较偏向使用这种格式喔!
变量的设定规则
1.变量与变量名以一个等号 “=”来连接
2.等号两边不能直接接空格符
3.变量只能是英文字符或者数字,但是不能以数组开头
4.变量内容若有空格,可以只用双引号或者单引号将变量内容结合起来。
a)双引号内的特殊字符可以保留原有的特性。如$
b)单引号内的内的特殊字符则仅为一个字符(纯文本)
5.可以使用转义字符将特殊字符转换为一般字符。如\Enter 、 \$ 空格符、!等
6. 在一串命令中,还需要其他命令提供信息,可以使用反单引号,`命令` ,或者“$(命令)”;
例如
"VERSION=$(uname-r)";
7.如果要累加变量内容,可以使用 “$变量名称"累加内容。
例如. PATH="$PATH":/home/bin
8 若变量需要在其他子程序中执行,则需要以export来使变量变成环境变量。
例如
>export PATH
9. 通常大写字符为系统默认变量,自行设置的变量可以使用小写字符,方便判断
10. 取消变量的方法为使用 “unset 变量名称”,
范例
范例一:设定一变量 name ,且内容为 VBird
[dmtsai@study ~]$ 12name=VBird
bash: 12name=VBird: command not found... <==屏幕会显示错误!因为不能以数字开头!
[dmtsai@study ~]$ name = VBird <==还是错误!因为有空白!
[dmtsai@study ~]$ name=VBird
范例六:如何进入到您目前核心的模块目录?
[dmtsai@study ~]$ cd /lib/modules/`uname - - r`/kernel
[dmtsai@study ~]$ cd /lib/modules/$(uname - - r)/kernel # 以此例较佳!
11.2.3 环境变量的功能
用env查看环境变量与常见环境变量说明
env environment (环境的缩写),是列出所有的环境变量。
范例
范例一:列出目前的 shell 环境下的所有环境变量与其内容。
[dmtsai@study ~]$ env
HOSTNAME=study.centos.vbird <== 这部主机的主机名
TERM=xterm <== 这个终端机使用的环境是什么类型
SHELL=/bin/bash <== 目前这个环境下,使用的 Shell 是哪一个程序?
HISTSIZE=1000 <== 『记录指令的笔数』在 CentOS 默认可记录 1000 笔
OLDPWD=/home/dmtsai <== 上一个工作目录的所在
LC_ALL=en_US.utf8 <== 由于语系的关系,鸟哥偷偷丢上来的一个设定
USER=dmtsai <== 使用者的名称啊!
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... <== 一些颜色显示
MAIL=/var/spool/mail/dmtsai <== 这个用户所取用的 mailbox 位置
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
PWD=/home/dmtsai <== 目前用户所在的工作目录 (利用 pwd 取出!)
LANG=zh_TW.UTF-8 <== 这个与语系有关,底下会再介绍!
HOME=/home/dmtsai <== 这个用户的家目录啊!
LOGNAME=dmtsai <== 登入者用来登入的账号名称
_=/usr/bin/env <== 上一次使用的指令的最后一个参数(或指令本身)
常见环境变量说明:
HOME :代表用户主文件夹。
SHELL:告知我们目前这个环境使用的shell是哪个程序?linux默认使用的是/bin/bash;
HISTSIZE:这个与历史命令有关,即我们曾经使用的历史命令被记录下来,记录的条数由这个值设置;
MAIL:当使用mail命令收信时,会获取这个值
PATH:执行文件查找的路径,目录与目录之间用冒号分割。
LANG:这个重要,就是语系数据,很多信息都会用到它。
RANDOM:这是随机数变量。
用set 查看所有变量(含有环境变量与自定义变量)
是什么
bash 可不只有环境变量,还有一些与 bash 操作接口有关的变量,以及用户自己定义的变量存在的。
范例
[dmtsai@study ~]$ set
BASH=/bin/bash <== bash 的主程序放置路径
BASH_VERSINFO=([0]="4" [1]="2" [2]="46" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")
BASH_VERSION='4.2.46(1)-release' <== 这两行是 bash 的版本啊!
COLUMNS=90 <== 在目前的终端机环境下,使用的字段有几个字符长度
HISTFILE=/home/dmtsai/.bash_history <== 历史命令记录的放置文件,隐藏档
HISTFILESIZE=1000 <== 存起来(与上个变量有关)的文件之指令的最大纪录笔数。
HISTSIZE=1000 <== 目前环境下,内存中记录的历史命令最大笔数。
...
# 有许多可以使用的函式库功能被鸟哥取消啰!请自行查阅!
使用export:自定义变量转成环境变量
tips
子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自定义变量
11.2.4 影响显示结果的语系变量(local)
查看支持的语系:
>local -a
整个系统定义的默认语系在/etc/sysconfig/i18n
11.2.5 变量的有效范围
在鸟哥的这个章节中,基本上你可以这样看待:
环境变量=全局变量
自定义变数=局部变量
11.2.6变量的键盘读取、数组与声明:read、array、declare
读入来自键盘的变量:read
read [-pt] variable
-p: 后面可接提示符
-t:后面接等待的秒数。不会一直等待用户
例子:
>read -p "pleas enter your name:" -t 30 named
pleas enter your name: abc
>echo $named
abc
声明变量的类型:declare / typeset
declare [-aixr] variable
-a : 定义variable 类型为数组
-i:定义variable 类型为整形integer
-x:用法与export一样,将后面的variable定义为环境变量
-r:定义variable为只读,该变量不能被更改 也不能重设。
例子:
>sum=1+2+3
>echo $sum
1+2+3
>declare -i sum=1+2+3
>echo $sum
6
数组类型:array
设置方法:
>var[1]=a
>var[2]=b
>echo ${var[1]}
a
数组的读取,建议直接使用${数组}来读取,会比较正确无误
11.2.7 与文件系统及程序的限制关系:ulimit
bash可以限制用户某些系统资源,包括可以打开文件的数量、可以使用cpu的时间,可以使用内存的总量等。
语法:
>ulimit [-SHacdfltu] [配额]
-H:hard limit 严格设置,必定不能超过这个设置的数值
-S:soft limit 警告的设置,可以超过这个设置值,会有警告信息
-a:后面不接任何设置参数,可以列出所有的限制额度。
-c:限制每个内核文件的最大内容。当某系进程发生错误时,系统可能将该进程在内存中的信息写入文件,这种文件成为内核文件;
-f:shell可以创建的最大文件容量,单位为kb 一般设为2GB;
-d:进程可以使用的最大断裂内存容量
-l:可用于锁定(lock)的内存容量
-t:可使用的最大cpu时间,单位为秒
-u:单一用户可使用的最大进程(process)数量
11.2.8 变量内容的删除、替代、与替换
变量内容的删除与取代
语法
${变量#关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最短数据删除
${变量##关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最长数据删除
${变量%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最短数据删除
${变量%%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最长数据删除
${变量/旧字符串/新字符串} 若变量内容符合『旧字符串』则『第一个旧字符串会被新字符串取代』
${变量//旧字符串/新字符串} 若变量内容符合『旧字符串』则『全部的旧字符串会被新字符串取代』
范例
变量的测试与内容替换
11.3 命令别名与历史命令
11.3.1 命令别名设置:alias 、 unalias
范例
[dmtsai@study ~]$ alias lm='ls - - al | more'
11.3.2 历史命令:history
语法:
>history [n]
>history [-c]
>history [-raw] hisfiles
n : 数字,列出最近n条命令
-c:将目前的shell中所有的history删除
-r:将hisfile的内容读到 目前这个shell的history中
-w:将目前的history 写到 hisfile文件中
history 相关功能
>! number
>! command
>!!
number :数字,执行第number行的命令
command:由最近的命令向前搜索,以comand开头的命令,并执行
!!执行上一个命令
11.4 bash shell的操作环境
11.4.1路径与命令查找顺序
基本上命令的运行顺序可以这样看
1.以相对路径或者绝对路径执行命令。例如"/bin/ls" 、"./ls"
2.由alias 找到命令来执行
3.由bash内置的(builtin)命令来执行
4.通过PATH这个变量来查找到第一个命令来执行
11.4.2 bash的登录与欢迎信息:/etc/issue 、 /etc/motd
>cat /etc/issue
centos relead 5.3
kernel \r an \m
这就就登录后欢迎页面
issue这个文件也是使用反斜杠作为变量的调用
可以使用man issue 配合man mingetty查看
\d:本地端的时间
\l:显示第几个中断接口
\m:显示硬件等级(i386/i486)
\n:显示主机网络名称
\o:显示 domain name
\r:操作系统的版本 相当于 uname -r
\t:显示本地端时间的时间
\s:操作系统名称
\v:操作系统的版本
11.4.3 bash的环境配置文件
login 与nologin shell
login shell:取得bash时需要完整的登录流程,就成为login shell。
nologin shell:取得bash接口的方法不需要重复登录的举动
一般来说 login shell 只会读取这两个配置文件
1. /etc/profile (这是系统整体的设置,最好不要修改)
2.~/.bash_login 或者 ~/.bash_profile 或者 ~/.profile
/etc/profile(login shell)
可vim打开阅读下这个文件的内容。这个配置文件可以根据用户标识符(UID)来决定很多重要的变量数据。没事不要随便改这个数据。
/etc/profile 还会调用外部的设置数据, 下面这些数据会依次调用上来,/etc/profile.d/*.sh 、 /etc/sysconfig/i18n、
~/.bash_profile (login shell)
个人偏好设置文件,在login shell 的bash的环境中,所有读取的个人偏好设置主要有三个,依次分别为
1.~/.bash_profile
2.~/.bash_login
3.~/.profile
只会读取上面中的一个,而读取顺序会按照上面顺序读取。
source :读入环境配置文件的命令
由于login shell 都是login shell 的时候读取配置文件,如果将配置写入上述文件后,一般需要注销再登录该配置文件才会生效。
可以只用 sourc命令或者.(小数点) 将配置文件的内容读到当前的shell当中。
语法:
>source 配置文件名
例如:>source ~/.bashrc
non-login shell 会读
~/.bashrc
其他配置文件
/etc/man.config
这个文件规定了使用man page 的路径去哪里去找。简单说 这个文件规定了执行man的时候该去哪里查看数据
~/.bash_history
默认情况下 我们的历史命令就会记录到这里。
~/.bash_logout
这个文件记录 当我们注销bash后,系统帮我们在做什么 我们再离开
11.4.4 终端机的环境设置
11.4.5通配符与特殊符号
常用的通配符
* :0到多个任意字符
?:代表一定有一个字符
[] : 同样代表一定有一个中括号内的字符
[-]:编码顺序内的所有字符。例如[0-9] 0到9之间的所有数字
[^] :例如 [^abc] 代表一定有一个字符,是非 a、b、c的
特殊符号:
#:注释
\:转义符号
|:管道
;:连续命令执行
~:用户主文件夹
$:使用变量前导符,
&:作业控制, 将命令变成背景下工作
! :逻辑运算符意义上的 非
/:路径符号,目录分割符
> 、>> : 数据流重定向,输出导向,分别是 “替换” 与“累加”
<、<<:数据流重定向,输入导向
'' :单引号,不具有变量置换的功能
"" :双引号 有变量置换的功能
`` :反单引号,中间为可以先执行的命令,也可以使用$()
( ) :中间为子shell的起始与结束
{} :中间为命令块的组合
11.5 数据流重定向
11.5.1 什么是数据流重定向
standard output 与standard error output
1>:以覆盖的方式将正确的数据输入到指定文件或者设备上
1>>:以累加的方式将....
2>:以覆盖的方式将错误数据....
2>>:以累加的方式将....
例如:将正确信息和错误信息分别放到不同的文件中
> find /home -name .barsh > list_right 2>list_error
dev/null 垃圾桶黑洞设备与特殊写法
dev/null可以将任何导向这个文件的信息吃掉。
例如:不在屏幕输入错误信息,也不写入文件
>find /home -name dddd 2>/dev/null
standard input : <与<<
11.5.2 命令执行的判断依据: && || , ;
不考虑命令相关性的连续命令执行:cmd1;cmd2
$?(命令回传码) 与 && 或 ||
两个命令有相依性
cmd1 && cmd2 :若cmd1执行完毕且正确执行($? =0) 和执行cmd2
cmd1 || cmd2 :若cmd1 执行完毕且且为错误($? 不等于 0) 则执行cmd2
11.6 管道命令pipe
11.6.1 选取命令 cut 和grep
cut:将一段信息切出来
语法:
>cut -d'分隔符' -f fields
>cut -c 字符范围
-d : 后面接分割字符 与-f一起使用
-f:依据-d 的分割字符,将一段信息切割成为数段,-f 选取第几端的意思
-c :以字符为单位取出固定的字符区间
cut的主要用途在于同一行里面的数据进行分解,进行切割以去的我们想要的数据;
例子:
>echo %PATH | cut -d ';' -f 5
以分号分割,并取出第五个
>echo %PATH | cut -d ';' -f 5,3
取第3 和5个
>echo %PATH | cut -c 12-
取12个后的所有字符
>echo %PATH | cut -c 12-20
取 12到第20个
grep 命令
分析一行信息,如果该行有我们要的数据,就将该行那出来;
语法:
grep [-avinv] [--color=auto] '查找字符串' filename
-a:将binary 文件以text的文化的方式查找数据;
-c:计算找到 “字符串”的次数
-i:忽略大小写
-n:顺便输出行号
-v:反向选择,即显示出没有 查找字符串的那一行
--color=auto: 可以将找到关键字加上颜色;
11.6.2 排序命令 sort 、wc、uniq
sort:帮我们进行排序
语法
>sort [-fbMnrtuk] [file or stdin]
-f:忽略大小写的差异
-b:忽略最前面空格的部分
-M:以月份的名字来排序,如JAN,DEC
-n:使用纯数字来排序(默认是以文字类型来排序的)
-r:反向排序
-u:就是uniq,相同的数据只出现一次
-t:分隔符,默认是[Tab]键来分割
-k:以哪个区间 (filed)来进行排序的意思
例子:
将内容以:分割,并以第三列来排序
>cat /etc/pass -t ';' -k 3
uniq:如果排序完成,想要将重复的数据仅显示一列
>uniq [-ic]
-i:忽略大小写
-c:进行计数
例子
使用last将账号列出来,仅取出账号列,进行排序后仅取出一位
>last | cut -d ' ' -f1 | sort |uniq
wc : 计算输出信息的整体数据,例如 /etc/man.config 这个文件有多少字,多个行,多少个字符。
语法
>wc [-lwm]
-l:仅列出行
-w:仅列出多少个字(英文单词)
-c:多少个字符
11.6.3 双向重定向:tee
> 会将数据流整个传送给文件或者设备,因此除非去读取这个文件或设备,否则就无法继续使用这个数据流
tee 会将数据流送与文件和屏幕,可以让下个命令继续使用
语法:
>tee [-a] file
-a : 以累加的方式输入的到文件
例子
>last | tee last.list |cut -d “ ”-f1
11.6.4 字符串转换命令:tr,col,join,paste,expand
tr 可以用来删除一段信息当中的文字,或者进行文字信息的替换
语法:
>tr [-ds] SET1
-d:删除信息当中的SET1这个字符串
-s : 替换掉重复的字符
例子:
将last 输入信息中的所有小写字母替换成大写字母
>last | tr [a-z] [A-Z]
将/etc/passwd 输出信息中的 冒号删除
>cat /etc/passwd | tr -d ':'
col
语法:
>col [-xb]
-x:将 [Tab] 键替换成相等的 空格
-b:在文件内有反斜杠时,仅保留反斜杠最后接的那个字符
join :处理两个文件的数据,将两个文件当中,有相同数据的那一行加到一起
语法:
>join [-ti12] file1 file2
-t :join 默认以空格分隔数据,并且对比”第一个字段“的数据 如果两个文件相同,则键两条数据连连城一行;且第一个字段放在第一个个
-i:忽略大小写
-1:数字1 ,代表第一个文件要用哪个字段来分析的意思
-2:数字2,代表第二个文件要用哪个字段来分析的意思
paste:这个要比join简单的多,join必须要对比两个文件的相关性,而paste就是直接将两行贴在一起。
语法
>paste [-d] file1 file2
-d:后面可以接分隔符,默认是以 [Tab] 来分割
-:如果file 部分写成了 - ,代表标准输入
expand :就是将[Tab] 键转换成空格
语法:
>expand [-t] file
-t:后面接数字,自定义一个tab 替换成多少个空格
11.6.5 切割命令: split
如果文件太大,导致一些便携设备无法复制粘贴,可以使用split,将大文件切成若干小文件
语法:
>spilt [-bl] file PREFIX
-b:后面接欲切成的文件大小 ,可接单位 如b k m等
-l:以行数来进行切割
PREFIX:代表前导符,可作为可切割文件的前导文字
11.6.6 参数代换:xargs
args 是arguments的缩写,xargs是 产生某个命令的参数。xargs可以读入stdin的数据,并且以空格或者断行字符进行分辨,将stdin的数据分割成argumens。因为是以空格符进行分割的,如果一些文件或者其他意义的名词中含有空格时,xargs可能会出现误判
语法
>xargs [-0epn] command
-0:如果输入stdin含有特殊字符,例如 \ 空格键等字符信息时,这个参数可以将它还原成一般字符,这个参数参数可以用于特殊状态
-e:这个是EOF 的意思,后面可以接一个字符串,当xargs 分析到这个字符串时,就会停止继续工作
-p:在执行每个命令的参数时,都会询问用户的意思
-n:后面接次数,每次command执行时,要使用几个参数的意思。
11.6.7 关于减号-的用途
在管道命令中,经常会使用前一个明林的stdout作为这次的stdin,某些命令需要用到文件名在处理时,该stdin与stdout可以使用减号来替代
![](/qrcode.jpg)