1 内建命令
父子Shell是相对的,描述了两个Shell进程的fork关系,父Shell指在控制终端或xterm窗口给出提示符的进程,子Shell是由父Shell创建的进程
Shell命令可分为内建命令(built-incommand)和外部命令(external command)
内建命令是由Shell本身执行的命令
外部命令由fork出来的子Shell执行
内建命令不创建子Shell,外部命令创建子Shell,因此,内建命令的执行速度要比外部命令快
内建命令就是包含在bash Shell工具包中的命令,内建的英文单词built-in也说明了这一点,内建命令是bash Shell的骨干部分
保留字(reserved words)也是bash Shell的骨干部分,保留字对于bash Shell具有特殊的含义,用来构建Shell语法结构,for、if、then、while、until等都是保留字,但是,保留字本身不是一个命令,而是命令结构的一部分
(1) 冒号:
冒号可以表示永真,相当于TRUE关键字,
Eg
#!/bin/bash
declare -i i=0
while : ;
do
if [ $i -eq 10 ]
then
break
fi
echo $((++i))
done
冒号可以用于清空一个文件,
anders@anders-virtual-machine:~/code/shell/subandthread$cat file
hello world
anders@anders-virtual-machine:~/code/shell/subandthread$ :>file
anders@anders-virtual-machine:~/code/shell/subandthread$cat file
(1) 圆括号命令
圆括号结构能够强制将其中的命令运行在子Shell中,它的基本格式为:
(
command 1
command 2
…
command n
)
圆括号内的n条命令在子Shell中运行,bash版本3之后定义了内部变量BASH_SUBSHELL,该变量记录了子Shell的层次
Eg: subvar.sh
#!/bin/bash
echo "the level of father shell is $BASH_SUBSHELL"
outvar=outvar
(
echo "the level of sub shell is $BASH_SUBSHELL"
innervar=innervar
echo "outvar=$outvar" #子shell继承了父shell的变量
echo "innervar=$innervar"
)
echo "the level of father shell is $BASH_SUBSHELL"
if [ -z $innervar ]
then
echo "the innervar is $innervar"
else
echo "the outvar is $outvar"
fi
运行结果:
anders@anders-virtual-machine:~/code/shell/subandthread$./subvar.sh
the level of father shell is 0
the level of sub shell is 1
outvar=outvar
innervar=innervar
the level of father shell is 0
the innervar is
由此可见:子shell继承父shell的变量 而父shell不会得到子shell中的变量
此外 父shell也不能使用子shell定义的环境变量!!!
2 Shell的限制模式
以前所讲的Shell都是运行在正常模式下的,Shell还有一种模式称为限制模式,简称rsh(Restricted Shell),处于限制模式的Shell下运行一个脚本或脚本片断,将会禁用一些命令或操作
Shell的限制模式是Linux系统基于安全方面的考虑,目的是为了限制脚本用户的权限,并尽可能地减小脚本所带来的危害
bash Shell的限制模式借鉴了Korn Shell的限制性命令和操作,限制的命令和操作包含如下几方面:
用cd命令更改当前工作目录的命令
更改重要环境变量的值,包括$PATH、$SHELL、$BASH_ENV、$ENV和$SHELLOPTS
输出重定向符号,包括>、>>、>|、>&、<>和&>符号
调用含有一个或多个斜杠(/)的命令名称
使用内建命令exec
使用set +r等命令关闭限制模式
使脚本运行在限制性模式下的两种方式:
第一种:set -r命令开启restricted选项
第二种: #!后的语句改成/bin/bash -r
3 进程和作业
进程号和作业号
Linux系统为每个进程分配一个数字以标识这个进程,这个数字就是进程号
创建该进程的Shell为此进程创建一个数字,也用于标识这个进程,这个数字称为作业号
作业号标识的是在此Shell下运行的所有进程,我们知道,Linux是多用户的系统,多用户可能开启了多个Shell,进程号就标识了整个系统下正在运行的所有进程
举例说明:
[root@jselab shell-book]# grep -r"root" /etc/* | sort > part1 &
[1] 4693
[root@jselab shell-book]# grep -r"root" /usr/local/* | sort > part2 &
[2] 4695
作业有两种运行方式:前台运行和后台运行
前台运行的作业指作业能够控制当前终端或窗口,且能接收用户的输入
后台运行的作业则不在当前激活的终端或窗口中运行,是在用户“看不见”的情况下运行
内建命令fg可将后台运行的作业放到前台,
而&符号使得作业后台运行,
CTRL+Z组合键可以使作业转入阻塞态,
bg命令可使阻塞态作业转入后台运行
fg、bg和jobs命令只能以作业号为参数来指定作业,这三个命令是不能使用进程号的
disown命令用于从Shell的作业表中删除作业,作业表指得就是由jobs命令所列出的作业列表
wait命令用于等待后台作业完成,
4 信号
信号是Linux进程间通信的一个重要而复杂的概念,信号是在软件层次上对中断机制的一种模拟
信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达
信号来源:硬件来源和软件来源
组合键 | 信号类型 | 意义 |
CTRL+C | INT信号,即interrupt信号 | 停止当前运行的作业 |
CTRL+Z | TSTP信号,即terminal stop信号 | 使当前运行的作业暂时停止(转入阻塞态) |
CTRL+\ | QUIT信号 | CTRL+C的强化版本,当CTRL+C无法停止作业时,使用此组合键 |
CTRL+Y | TSTP信号,即terminal stop信号 | 当进程从终端读取输入数据时,暂时停止该进程 |
对于shell能执行 停止 暂停等功能,是因为向shell发送了了信号。
如表中信号:INT TSTP等
CTRL+C,INT信号,退出作业
CTRL+\, QUIT信号, CTRL+C的强化版本
CTRL+Y组合键实际上与CTRL+Z组合键是类似的,都是向进程发送TSTP信号,表示将进程暂时停止
kill命令可以通过进程号、作业号或进程命令名向任何作业发送信号
kill –l列出kill命令能发出的所有信号
5 trap命令
trap是Linux的内建命令,它用于捕捉信号
指定收到某种信号时所执行的命令
trap command sig1 sig2 …sigN
trap命令表示当收到sig1、sig2、…、sigN中任意一个信号时,执行command命令,command命令完成后脚本继续收到信号前的操作,直到脚本执行结束
eg
#!/bin/bash
trap "echo 'execute trap !'" INT #接收 INT信号 即ctrl +c
count=1
while : ;
do
echo "this is $count"
let "count+=1"
sleep 5
done
运行结果:每当 按下ctrl+c的时候都会被trap接收到,然后执行引号中的命令
anders@anders-virtual-machine:~/code/shell/subandthread$./trap1.sh
this is 1
this is 2
^Cexecute trap !
this is 3
^Cexecute trap !
this is 4
^Cexecute trap !
trap命令还可以
忽略某些信号,即进程收到某些信号后不做任何处理,我们只要简单将trap命令的command用空字符串代替即可(""或'')
#!/bin/bash
trap "" TERM SIGKILL INT
while :; do
#let count=count+1
#echo "This is the $count sleep"
sleep 5
done