第十章 认识与学习BASH
Shell的介绍
硬件、核心与shell
-
电脑的运行即硬件的运行,硬件的运行是由操作系统的内核(Kernal)来控制的。由于内核控制管理整个系统,如果让用户随意操作内核,当操作不当的时候就会引发很多不必要的问题。所有有了Shell,shell是用户和内核间的一层媒介,用户通过shell和内核沟通,进行一些操作。shell就像裹在内核外的一层壳,用户想要和内核沟通就要敲几下外壳,才能进行沟通。
-
使用shell的原因是:
- shell在各种linux发行版都是一样的
- 命令行模式速度较快
- Bash shell的功能
- 记录历史命令
-
bash会记录使用过的命令,用方向键中的上下键就可以找到以前使用过的命令,也就是说我们可以很方便的查询到我们以前所做的操作。
-
注意的是:我们的命令记录都会被记录到用户目录内的
.bash_history
,而~/.bash_history
记录的是前一次登陆以前所执行过的命令,目前登陆状态中执行过的命令会被缓存在内存中,只有退出登陆后,这些记录才会被记录到.bash_history
中 -
命令和文件补全功能(Tab)
- [Tab] 接在一串命令的第一个字后面,为命令补全
- [Tab]接在一串命令的第二个字后面,为文件补全
- 若安装bash-completion软件,则再某些命令后面使用[Tab],可以补全命令的选项或参数
-
命令别名的设置(使用alias命令)
alias lm='ls -l' # lm就相当于ls -l,可以直接使用lm来执行,更加方便 任务管理,前台、后台控制
-
shell可以控制任务的执行状态,可以放在前台执行,也可以抛到后台去执行
-
程序化脚本(shell 脚本)
-
通配符
查询命令是否为bash shell的内置命令(使用type命令)
Linux命令分为内置命令和外部命令
- 内置命令在系统启动时就会加载到内存当中,所以执行速度很快
- 外部命令只有当用户需要使用时才会从硬盘读入到内存当中
那么如何查看一个命令的类型呢,就需要使用到type命令
type [-tpa] command_name
不加任何参数:type会显示command是外部命令还是内置命令
-t: type会显示三种结果,表示一定的意义
file 表示该命令为外部命令
alias 表示该命令为命令别名的名称
builtin 表示该命令为shell内置命令
-a: 会有PATH变量定义的路径中,将所有含command_name的命令都列出来,包括alias
- 注意: type主要是用来找出执行文件而不是一般文件名,如果后面接的名称并不能以执行状态被找到的话,该名称不会被显示出来,所以type用来寻找命令
命令的执行和编辑
-
\ 用来转义紧接在它后面的字符,如[Enter]用来转义换行符,常用来在shell中进行命令的换行输入
-
命令的编辑
- [Ctrl]+u:从光标处向前删除命令串
- [Ctrl]+k:从光标处向后删除命令串
- [Ctrl]+a:让光标移动到整个命令串的最前面
- [Ctrl]+e:让光标移动到整个命令串的最后面
Shell的变量
变量的定义:
变量就是以一组文字或符号,来替换一些设置或保留的数据
变量的使用和设置
变量的使用(echo)
echo $variable # 查看变量的内容
如: echo $PATH
变量的设置
变量设置的规则:
-
变量与变量内容间用 = 连接
-
等号两边不能接空格
-
变量名只能是英文字母或数字,且开头字符不能是数字
-
双引号内的字符可以保有原本的特性,可以代表其他含义
“$LANG” 即 zh_CN.UTF8
- 单引号内的特殊字符仅为一般字符,即表示字符本身,不代表其他含义
“ LANG
- 注意:单双引号必须成对
变量的一些设置:
-
在一串命令中,``或$()中的命令会先执行,执行得出的结果将作为外部的输入信息
-
扩增变量内容时,可使用“ {PATH}来累加内容
如:"$PATH":/home/bin 或 ${PATH}:/home/bin # PATH变量中增加/home/bin
- 可以使用export命令使变量变为环境变量(对任一进程都可用)
因为在一般情况下,子进程仅会继承父进程的环境变量,不会继承父进程的自定义变量,所以父进程的自定义变量在子进程中是不能使用的,但将之设置为环境变量,就可在子进程中使用了。
环境变量能被子进程使用的原因––-内存配置:
- 当启动一个shell时,系统会分配一内存区域给shell使用,此内存中的变量可以让子进程使用
- export命令即将自定义变量写入该内存区域中
- 打开另一个shell(即打开子进程时),子进程会将父进程的环境变量所在的内存区域导入自己的环境变量区块中
- 取消变量的方法为使用unset命令
unset myname # 取消myname这个变量
环境变量的功能
环境变量的查看
env
命令会列出所有环境变量与其内容set
命令不仅会显示环境变量,其他在bash内的变量也会显示出来
一些变量的含义
-
HOME:代表用户的根目录
-
SHELL:代表当前环境使用的shell
-
PATH:执行文件查找的路径
-
LANG:语系数据
-
PS1:提示字符的设置
-
$:美元符号本身也是个变量,代表目前这个shell的进程号PID
-
?:上一个命令的返回值。我们执行命令后都会返回一个执行后的代码,成功执行代码返回0,错误执行返回其他数值,代表错误代码。
变量的键盘读取、数组、声明
-
变量的键盘读取(read命令)
-
read命令可以从标准输入中读取数据作为变量的内容
read [-pt] variable
-p:后接提示字符(提示输入)
-t:后接可等待的秒数,用户需要在指定时间内输入 作为变量内容 的数据
- 声明变量的类型(declare或typeset)
declare [-aixr] variable
-a:将variable定义为数组类型
-i:将variable定义为整数类型
-x:将variable变成环境变量
-r:将variable设为readonly,即只读状态
- Linux中变量类型默认为字符串
- bash中的数值运算,只限整数
数组类型
设置方式:var[index]=content
如:var[1]="1"
var[2]="2"
var[3]="3"
可以直接以${数组}来读取,如echo ${var[1]}
限制用户的使用资源(ulimit)
ulimit [-SHacdfltu] [配额]
-f:该shell可以建立的最大文件容量,单位为KB
- 恢复ulimit设置的办法是 注销之后再登陆
变量内容的删除和替换
- 变量的内容除了可以直接设置外,还可以进行微调,如删除、替换等
删除和替换
- 从前往后删除
${variable#匹配格式} #从前往后删除符合替换文字的最短内容
${variabel##匹配格式} #从前往后删除符合替换文字的最长内容
例:${PATH#/*local/bin} 在PATH变量中从前往后删除与/*local/bin匹配的最短内容
- 从后往前删除
${variable%匹配格式} #从后往前删除符合替换文字的最短内容
${variabel%%匹配格式} #从后往前删除符合替换文字的最长内容
- 替换
${variabel/旧字符串/新字符串} # 变量内容符合旧字符串的**第一个字符串**被新字符串替换
${varable//旧字符串/新字符串} # 变量内容符合旧字符串的**所有内容**被新字符串替换
命令别名和历史命令
命令别名的设置(alias、unalias)
alias 别名 'command -parameter' # 创建一个命令别名
unalias 别名 # 取消设置的命令别名
Linux中清楚屏幕的命令为clear
历史命令(history)
- 查询我们执行过的命令
history # 列出所有执行过的命令
history [n]
history [-c]
history [-raw] histfiles
选项和参数:
[n] : 列出最近执行的n条命令
[-c] : 清除history的历史执行命令
[-a]:将目前新增的history命令加入到histfiles中,如没有加histfiles,则默认写入~/.bash_history
-r: 将histfiles的内容读到目前使用shell的history记录中
-w:将目前的history记录内容写入到histfiles
- 历史命令的读取和记录:
- 当我们登陆Linux后,系统会自动从/.bash_history中读取以前执行过的命令。而/.bash_history记录的条数是由HISTFILESIZE这个变量所控制的
- 当我们注销之后,系统会将最近的HISTFILESIZE条命令记录到~/.bash_history中(或者使用history -w强制更新)
- 利用历史命令记录来执行命令
!number # 执行第number条命令
!command # 由最近使用的命令向以前查找命令开头为command的那个命令,并执行
!! # 执行上一个命令(或者使用方向键↑)
-
开启多个bash时,每一个bash都会由HISTFILESIZE条命令写入内存之中,最后一个注销的用户的历史命令时最后写入的数据,会覆盖之前的数据。
-
我们可以记录以前使用的命令,但无法记录他们使用时的时间
Bash shell的操作环境
命令与命令查找顺序
-
在我们的系统中会有不少同名的命令,那么当我们输入一个命令时,被执行的到底是哪一个命令呢?系统查找时会依据一定的顺序依次查找,最先找到的即所执行的。
-
命令运行的顺序:
- 以相对/绝对路径执行命令
- 由alias找到命令来执行
- 由bash内置的命令执行
- 通过PATH变量的顺序查找命令,第一个命令用来执行
bash的登陆和欢迎信息
-
bash的登陆信息是写在
/etc/issue
中的 -
issue内各代码的意义:
- /d 本地端时间的日期;
- /l 显示第几个终端机接口;
- /m 显示硬件的等级 (i386/i486/i586/i686…);
- /n 显示主机的网络名称;
- /o 显示 domain name;
- /r 操作系统的版本 (相当于 uname -r)
- /t 显示本地端时间的时间;
- /s 操作系统的名称;
- /v 操作系统的版本
-
除此之外,还有一个
/etc/issue.net
文件,这是提供给telnet这个远程登陆程序使用,当我们使用telnet连接到主机时,登陆画面就会显示/etc/issue.net
中的内容 -
登陆之后用户会收到的消息是写在
/etc/motd
中的
bash的环境配置文件
-
bash启动后会读取指定的配置文件,来规划好bash的操作环境。
-
我们有两种shell,login shell和non-login shell,他们的区别是登陆的方式不同,bash所读取的配置文件也不相同
login shell
-
经由完整的登陆流程(输入账号密码)所取得的shell就叫做login shell,login shell一般会读取两个配置文件
/etc/profile
和~/.bash_profile
-
/etc/profile
- 该文件是每个用户登陆取得bash时一定会读取的配置文件,用来设置系统的整体环境,该文件设置的变量主要有:
- PATH
- HISTSIZE:历史命令记录条数
- umask
- 此外,
/etc/profile
还用去调用外部的配置文件,/etc/profile.d/.sh
、/etc/locale.conf
、/usr/share/bash-completion/completions/
- 该文件是每个用户登陆取得bash时一定会读取的配置文件,用来设置系统的整体环境,该文件设置的变量主要有:
-
~/.bash_profile
-
bash在读完/etc/profile,且调用完外部得配置文件后就会读取用户的个人配置文件
~/.bash_profile
~/.bash_login
~/.profile
-
bash会读取依次读取上面的文件,且只读取一个,即首先读取
~/.bash_profile
,~/.bash_profile
不存在再读取~/.bash_login
-
-
最后读取
~/.bashrc
文件
source 配置文件名(可以不注销登陆就使该配置文件生效)
non-login shell
- non-login shell 只会读取
~/.bashrc
,此外还会读取/etc/bashrc
(centos所特有的),/etc/bashrc
帮我们定义以下内容:- 根据不同的UID设置umask的值
- 根据不同的UID设置PS1变量(即提示字符的内容)
- 调用
/etc/profile.d/.sh
其他影响bash的配置文件
-
/etc/man_db.conf
规范了使用man时,man page的路径去哪里寻找
-
~/.bash_history
历史命令的记录,每次登陆bash后,bash会先读取这个文件,将使用过的命令记录读取到内存中
-
~/.bash_logout
记录注销bash后所要执行的操作
终端的环境设置
- 登陆终端时,会自动获取终端输入环境的设置
stty [-a]
-a:列出所有的按键和按键内容,其中^表示[Ctrl]
set [-ucCHhmBx] 用来设置终端的输入/输出 环境
数据流重定向
数据流重定向:将输出到屏幕上的数据重定向至其他文件中
首先明确三个概念:
-
standard input
由键盘输入的数据
-
standard output
命令执行所返回的正确信息
-
standard error output
命令执行失败所返回的错误信息
-
数据流重定向可以将standard output、standard error output传送到其他文件或设备(如果文件不存在则会自动创建),传送所用的特殊字符如下所示:
- standard input:代码为0,使用<或<<
- standard input:代码为1,使用>或>>
- standard error output:代码为2,使用2>或2>>
>和>>的区别:
-
1> :以覆盖的方式将 正确的数据 输出到指定文件或设备
-
>>1:以追加的方式将 正确的数据 输出到指定文件或设备
-
2>:以覆盖的方式将 错误数据 输出到指定文件或设备
-
2>>:以追加的方式将 错误数据 输出到指定文件或设备
-
注意数字代码与>间无空格
-
< :将原本需要由键盘输入的数据,改由指定文件来替换
-
<<:代表结束字符
1. find /home -name .bashrc > list_right 2>list_error
若find查询成功,将查询得到的数据写入list_right文件中,而不打印在屏幕上;若执行失败,则将错误信息写入list_error文件中
2. cat > catfile << "eof"
从标准输入中读取数据,输出至catfile文件中,且遇到eof字符便停止
3. cat > catfile < ~/.bashrc
从~/.bashrc中读取数据输出至catfile文件中
命令串的执行
不考虑命令相关性连续执行多个命令
使用,连接多个命令,这些命令会依次执行
考虑相关性执行命令串
使用 && 和 || :
- cmd1 && cmd2 :
- 若cmd1执行完毕且正确执行($?=0),则开始执行cmd2
- 若cmd1执行完毕且错误执行($?≠0),则不执行cmd2
- cmd1 || cmd2:
- 若cmd1执行完毕且正确执行($?≠0),则不执行cmd2
- 若cmd1执行完毕且错误执行($?=0),则开始执行cmd2
管道命令|
管道 | 可以将上一个命令的输出作为下一个命令的输入,是命令间的桥梁
注意:
- 管道命令仅能出合理标准输入,标准错误会被忽略
- 每个管道后面接的第一个数据一定是命令,且管道命令必须接受前一个命令的数据作为输入才能继续处理
ls -l /etc | less
ls命令执行的输出结果会作为less的输入
常用的管道命令
cut、grep、sort、wc、uniq、tee、tr、col、join、paste、expand、split、xargs
- 号的用途
- 号可以用来替代标准输入或标准输出
tar -cvf - /home | tar -xvf - -C /tmp/homework
将/home内的文件打包,但不传送到文件中,而是传送到标准输出中,后面的-即使用前一个命令的输出