第11章 认识与学习BASH
11.1 Shell
硬件、内核与Shell的关系
- Shell:提供用户使用计算机系统的接口;
- 内核:用于控制计算机硬件和系统资源;
- 硬件:最终响应用户做出的指示;
11.1.1 Shell
- Shell:能够提供用户控制应用程序的接口都能称为Shell;
- Shell(狭义):指的是命令行软件,包括本章要介绍的bash等;
- Shell(广义):除了命令行软件,还包括图形用户接口的应用程序;
11.1.2 系统支持的Shell
配置文件/etc/shells
配置文件/etc/shells
保存着当前系统上支持的合法Shell。系统的某些服务在运行过程中,会通过这个配置文件去检查用户能够使用的shell。
常见的Shell
/bin/sh
已经被 /bin/bash 所取代/bin/bash
Linux 默认的 shell。BASH(Bourne Again SHell)是基于GNU架构发展出来的,对Bourne Shell的增强版本;/bin/ksh
Kornshell 由 AT&T Bell lab. 发展出来的,兼容于 bash
- /bin/tcsh
整合 C Shell ,提供更多的功能
/bin/csh
已经被 /bin/tcsh 所取代/bin/zsh
基于 ksh 发展出来的,功能更强大的 shell
BASH Shell
Bash的优点
- history:记录用户使用过的历史命令,提供了用户审计功能;
- 命令与文件名的补全功能
- 可为命令配置别名(alias)
- 作业控制(job control):提供前台(forground)、后台(background)作业控制
- Shell脚本(Shell Scripts):支持命令的批量脚本化
- 支持通配符(Wildcard)
Bash的内建命令:type
type
命令用来查看一个给定的命令是外部命令,还是bash内建命令。
[root@www ~]# type [-tpa] name
选项与参数:
:不加任何选项与参数时,type 会显示出 name 是外部命令还是 bash 内建命令
-t :当加入 -t 参数时,type 会将 name 以底下这些字眼显示出他的意义:
file :表示为外部命令;
alias :表示该命令为命令别名所配置的名称;
builtin :表示该命令为 bash 内建的命令功能;
-p :如果后面接的 name 为外部命令时,才会显示完整文件名;
-a :会由 PATH 变量定义的路径中,将所有含 name 的命令都列出来,包含 alias
范例一:查询一下 ls 这个命令是否为 bash 内建?
[root@www ~]# type ls
ls is aliased to `ls --color=tty' <==未加任何参数,列出 ls 的最主要使用情况
[root@www ~]# type -t ls
alias <==仅列出 ls 运行时的依据
[root@www ~]# type -a ls
ls is aliased to `ls --color=tty' <==最先使用 aliase
ls is /bin/ls <==还有找到外部命令在 /bin/ls
范例二:那么 cd 呢?
[root@www ~]# type cd
cd is a shell builtin <==看到了吗? cd 是 shell 内建命令
使用反斜杠”\”来解决单行命令过长的问题
如果命令串太长的话,如何使用两行来输出?
[vbird@www ~]# cp /var/spool/mail/root /etc/crontab \
> /etc/fstab /root
在命令行末尾使用一个反斜杠“\”来对回车进行转义,这样就不会使命令被提交,达到在下一行继续输入命令的目的!
11.2 Shell的变量功能
11.2.1 变量
- 变量:是以一组文字或符号等,来取代一些配置或者一串保留的数据!
- 自定义变量
- 环境变量
11.2.2 变量的设置,取用,删除
变量的设置
- 使用等号“=”来对变量进行赋值,等号左边是变量名,等号右边是变量的内容。
- 注意等号两边不能有空格!
- 在bash中,调用没有赋值的变量名,则变量的内容默认为空!
[root@www ~]# echo $myname
<==这里并没有任何数据~因为这个变量尚未被配置!是空的!
[root@www ~]# myname=VBird #定义变量
[root@www ~]# echo $myname
VBird <==出现了!因为这个变量已经被配置了!
变量的取用
[root@www ~]# echo $variable #设置变量
取用的第1种方法:
[root@www ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
取用的第2种方法:
[root@www ~]# echo ${PATH}
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
删除变量:unset
[root@www ~]# unset variable
变量的设置规则
- 变量名与变量值以一个等号“=”相连接:
myname=VBird
; - 等号两边不能有空格符,如
myname = VBird
和my name=VBird
以及myname=VBird Tsai
都是错误的; - 变量名可以是英文字符和数字,但不能以数字开头,如
2myname=VBird
是错误的; - 变量值中存在空格符时,可以使用双引号”或单引号’将变量值包裹住,但两者有差异:
- 双引号中包含的特殊字符(如$等),可以保持原有特性,如
var="lang is $LANG"
则echo $var
会得到lang is en_US
; - 单引号中包含的特殊字符(如$等),将被视为一般字符处理,如
var='lang is $LANG'
则echo $var
会得到lang is $LANG
;
- 双引号中包含的特殊字符(如$等),可以保持原有特性,如
- 可使用反斜杠\作为转义字符,将特殊符号(如[enter], $, , 空格符,单引号,双引号等)变为一般字符,如
myname=VBird\'s\ name
,就将单引号和空白符转移为一般字符了。 - 在包含多个命令的单行命令语句中,若需要将一些命令的结果作为参数提供给其他命令使用,可以使用反单引号
`命令`
或$(命令)
将语句中的某些命令包裹住,如想要获得内核版本有这几种方法:
- 先
version=$(uname -r)
或version=`uname -r`
,然后echo $version
; - 直接
echo `uname -r`
或echo $(uname -r)
;
- 先
- 增加变量值内容时,可先取用变量,然后用“取得的值”与“欲增加的内容”再次赋值,如
PATH="$PATH":/home/bin
或PATH="${PATH}":/home/bin
,或PATH=${PATH}:/home/bin
; - 若该变量需要被当前Shell的其他子进程(子Shell和子程序)中调用,需要用
export
来使该变量变为环境变量,如export PATH
; - 通常系统默认变量用大写字符命名,用户自定义变量用小写字符命名,方便辨识;
- 使用命令
unset
来取消或删除某个变量,如删除myname变量:unset myname
;
实践
范例五:如何让我刚刚配置的 name=VBird 可以用在子 shell 的程序?
[root@www ~]# name=VBird
[root@www ~]# bash #进入到所谓的子Shell
[root@www ~]# echo $name #子Shell:再次的 echo 一下;
<==嘿嘿!并没有刚刚配置的内容喔!
[root@www ~]# exit #子Shell:离开这个子程序
[root@www ~]# export name #将name转变为环境变量!
[root@www ~]# bash #进入到所谓的子Shell
[root@www ~]# echo $name #子Shell:在此运行!
VBird <==看吧!出现配置值了!
[root@www ~]# exit #子Shell:离开这个子程序
范例六:如何进入到您目前核心的模块目录?
[root@www ~]# cd /lib/modules/`uname -r`/kernel
[root@www ~]# cd /lib/modules/$(uname -r)/kernel
每个Linux可以拥有多个内核版本,使用这种方法可以进入系统当前内核的模块目录。
11.2.3 环境变量
- 环境变量是指在操作系统中用来指定操作系统运行环境的一些配置参数。环境变量可以被当前Shell的子进程(包括子Shell与子程序)继续使用,而一般变量则不行!
- 每一个Shell都是一个进程,具有各自的PID;
- 当你在当前bash中输入命令
bash
,那么当前bash就会触发一个新的bash,这个新的bash就称为当前bash的子Shell(同时也是子进程),而当前bash则称为这个新bash的父Shell(同时也是父进程); - 子进程会继承父进程的环境变量,但不会继承父进程的自定义变量!
常见环境变量
HOME
代表用户的家目录。当使用cd ~
回到家目录时,~代表的就是这个变量,你可以直接echo ~
来查看;SHELL
指示当前系统所使用的Shell是哪种;HISTSIZE
当前可记录Bash历史命令的条数;MAIL
使用mail命令收邮件时,系统读取邮件的位置;PATH
可执行文件的查找路径;此变量中的目录有先后顺序;LANG
当前语系RANDOM
随机数变量,由/dev/random
生成随机数,取值范围介于0~32767之间;
与当前SHELL相关的非环境变量
PS1
命令提示符的配置;- $ 当前Shell的进程ID(PID, Process ID);每个Shell都是一个进程具有各自的PID;
?
上一个运行的命令的返回值,正常结束时返回0,非零值代表异常出错的错误代码;OSTYPE
,HOSTTYPE
,MACHTYPE
主机硬件与内核的等级;
查看所有环境变量与变量值:env
root@www ~]# env
HOSTNAME=www.vbird.tsai <== 这部主机的主机名
TERM=xterm <== 这个终端机使用的环境是什么类型
SHELL=/bin/bash <== 目前这个环境下,使用的 Shell 是哪一个程序?
HISTSIZE=1000 <== 『记录命令的笔数』在 CentOS 默认可记录 1000 笔
USER=root <== 使用者的名称啊!
LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:
or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=0
0;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=
00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;3
1:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00
;35:*.xpm=00;35:*.png=00;35:*.tif=00;35: <== 一些颜色显示
MAIL=/var/spool/mail/root <== 这个用户所取用的 mailbox 位置
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:
/root/bin <== 不再多讲啊!是运行文件命令搜寻路径
INPUTRC=/etc/inputrc <== 与键盘按键功能有关。可以配置特殊按键!
PWD=/root <== 目前用户所在的工作目录 (利用 pwd 取出!)
LANG=en_US <== 这个与语系有关,底下会再介绍!
HOME=/root <== 这个用户的家目录啊!
_=/bin/env <== 上一次使用的命令的最后一个参数(或命令本身)
使用set查看所有变量(环境变量与自定义变量)
[root@www ~]# set
BASH=/bin/bash <== bash 的主程序放置路径
BASH_VERSINFO=([0]="3" [1]="2" [2]="25" [3]="1" [4]="release"
[5]="i686-redhat-linux-gnu") <== bash 的版本啊!
BASH_VERSION='3.2.25(1)-release' <== 也是 bash 的版本啊!
COLORS=/etc/DIR_COLORS.xterm <== 使用的颜色纪录文件
COLUMNS=115 <== 在目前的终端机环境下,使用的字段有几个字符长度
HISTFILE=/root/.bash_history <== 历史命令记录的放置文件,隐藏档
HISTFILESIZE=1000 <== 存起来(与上个变量有关)的文件之命令的最大纪录笔数。
HISTSIZE=1000 <== 目前环境下,可记录的历史命令最大笔数。
HOSTTYPE=i686 <== 主机安装的软件主要类型。我们用的是 i686 兼容机器软件
IFS=$' \t\n' <== 默认的分隔符
LINES=35 <== 目前的终端机下的最大行数
MACHTYPE=i686-redhat-linux-gnu <== 安装的机器类型
MAILCHECK=60 <== 与邮件有关。每 60 秒去扫瞄一次信箱有无新信!
OLDPWD=/home <== 上个工作目录。我们可以用 cd - 来取用这个变量。
OSTYPE=linux-gnu <== 操作系统的类型!
PPID=20025 <== 父程序的 PID (会在后续章节才介绍)
PS1=