Linux shell编程之控制脚本之信号控制作业

控制脚本之信号控制作业

①信号基础

②产生信号

③捕捉信号

④运行模式

后台运行脚本

非控制台下运行脚本

⑤作业控制

作业控制只查看作业

作业控制之重启停止的作业

fg命令

bg命令

 


 

①信号基础

>>>Linux系统上通过Linux信号可以实现对脚本的控制

>>>bash shell会忽略SIGQUIT3)和SIGTERM15)的信号,会处理SIGHUP1)和SIGINT2)的信号

Linux常见的系统信号

常见信号

描述

1

SIGHUP

挂起进程

2

SIGINT

终止进程

3

SIGQUIT

停止进程

9

SIGKILL

 无条件终止进程

15

SIGTERM

可能的话终止进程

17

SIGSTOP

无条件停止进程但不终止进程

18

SIGSTP

停止或者暂停进程,但不终止进程

19

SIGCONT

继续停止的进程

说明:

        当bash shell收到SIGHUP信号时,bash shell会退出,但在退出之前,bash shell会将SIGHUP信号传给shell启动的所有进程(包括shell脚本)

        可以通过SIGINT信号去终端bash shell,当bash shell收到SIGINT信号时,会通知shell启动的所有进程,SIGINT信号意味着Linux内核会停止将CPU处理时间分配给收到该信号的shell

 


 

②产生信号

>>>bash shell允许键盘上的按键组合产生基本的Linux信号

产生信号分类

按键组合

描述

Ctrl+C

发送SIGINT信号到当前正在运行的作业,让作业终止

Ctrl+Z

发送SIGSTP信号,将一个正在前台执行的任务进程放到后台运行,并将任务进程挂起,此时状态为STOP

案例

[bei@localhost test]$ sleep 100
^Z
[1]+  Stopped                 sleep 100
[bei@localhost test]$ jobs
[1]+  Stopped                 sleep 100
#停止多个进程后
[beihuatao@localhost ~]$ jobs
[1]   Stopped                sleep 100
[2]   Stopped                 sleep 100
[3]-  Stopped                 sleep 100 : - 表示信号下一个处理的进程
[4]+  Stopped                 sleep 100 : + 表示信号处理的进程

说明:

bash shell会将shell中运行的每个进程称为作业(job)

bash shell会为每个作业分配一个唯一的作业号,方括号中[ ]的数字表示的是shell分配的作业号

Stopped表示作业在后台的状态为停止

可以使用ps命令查看已停止的作业,找到对应的PID,可以使用向作业发送SIGKILL信号的方式终止作业

案例

[bei@localhost test]$ ps -ef | grep "bei"
root      41490  41466  0 18:43 pts/1    00:00:00 su - bei
bei       41491  41490  0 18:43 pts/1    00:00:00 -bash
root      42614  42231  0 20:13 pts/2    00:00:00 su - bei
bei       42615  42614  0 20:13 pts/2    00:00:00 -bash
bei       42648  42615  0 20:14 pts/2    00:00:00 sleep 100
bei       42781  42615  0 20:36 pts/2    00:00:00 ps -ef
bei       42782  42615  0 20:36 pts/2    00:00:00 grep bei
[bei@localhost test]$ kill -9 42648
[bei@localhost test]$ ps -ef | grep "bei"
root      41490  41466  0 18:43 pts/1    00:00:00 su - bei
bei       41491  41490  0 18:43 pts/1    00:00:00 -bash
root      42614  42231  0 20:13 pts/2    00:00:00 su - bei
bei       42615  42614  0 20:13 pts/2    00:00:00 -bash
bei       42783  42615  0 20:36 pts/2    00:00:00 ps -ef
bei       42784  42615  0 20:36 pts/2    00:00:00 grep bei
[1]+  Killed                  sleep 100

说明:ps命令的第二列为PID,输入kill -9 PID即可终止进程

 


 

③捕捉信号

>>>默认情况下,shell脚本是不会去处理bash shell发送过来的信号

>>>可以使用trap命令指定shell脚本可以捕捉哪些信号

>>>当脚本收到了trap命令中列出的信号,trap命令会组织信号被shell处理,而在本地处理

     例:trap命令可以去监听SIGSTP信号,当脚本收到SIGSTP信号时,trap命令就会捕捉这个信号,让脚本不受影响

 

trap命令基本格式:

trap commands signals

>>>信号以空格分隔开,可以用数值,也可以用名称

>>>commands表示当捕捉到信号,想要执行的shell命令

>>>命令用引号引起来,每次阻止到指定信号,都会执行命令

案例

[bei@localhost test]$ cat signal.sh
#!/bin/bash
trap "echo 'sorry,the signal[Ctrl+C] has been trapped.'" SIGINT
count=1
while [ $count -le 5 ]
do
        echo "sleep $count"
        sleep $count
        count=$[ $count + 1 ]
done
echo "end"
[bei@localhost test]$ bash signal.sh
sleep 1
sleep 2
sleep 3
^Csorry,the signal[Ctrl+C] has been trapped.
sleep 4
^Csorry,the signal[Ctrl+C] has been trapped.
sleep 5
end

说明:

此案例中,使用trap命令去捕捉SIGINT信号,若SIGINT信号被捕捉到,无法终止脚本,而会显示一行文本

 


 

④运行模式

>>>大部分情况下,我们执行脚本是在命令行上直接运行,此时我们无法同时使用命令行进行其他操作,只有等待脚本执行结束

>>>当脚本运行时间过长时,如果需要使用命令行做其他事情,我们可以将脚本放入到后台去运行

 

后台运行脚本(与终端关联)

>>>可以使用 bash scripts & 这种方式将scripts脚本放入到后台运行

>>>脚本中的输出(标准输出或标准错误输出)都会打印在屏幕上

>>>每个后台进程都会绑定到该终端的绘画的终端上(pts/0),当终端会话进程退出,会终止该终端后台的进程

案例

[bei@localhost test]$ cat signal.sh
#!/bin/bash
count=1
while [ $count -le 5 ]
do
        echo "sleep $count"
        sleep $count
        count=$[ $count + 1 ]
done
echo "end"
[bei@localhost test]$ bash signal.sh &
[1] 43055
[bei@localhost test]$ sleep 1
sleep 2
sleep 3
sleep 4
[bei@localhost test]$
[bei@localhost test]$ ls -al
total 100
drwxrwxr-x. 2 bei bei 4096 Sep 25 21:10 .
drwxr-xr-x. 6 bei bei 4096 Sep 16 19:51 ..
-rw-rw-rw-. 1 bei bei  120 Sep 25 21:10 signal.sh
[bei@localhost test]$ sleep 5
pwd
/home/bei/linux/test
[bei@localhost test]$ end
[1]+  Done                    bash signal.sh

说明:

当脚本放入到后台执行时会有一个输出,如[1] 43055,
        其中[1]表示的是当前bash shell给这个作业分配的作业号,4305表式 分配给脚本的进程号PID

当脚本结束后,会有一个输出,如 [1]+  Done                    bash signal.sh     表示脚本已结束

     

 

非控制台下运行脚本(与终端不关联)

>>>需求:即使终端会话进程退出,在后台运行的脚本也不会退出,一直运行直到脚本自身运行完成

>>>可以使用nohup命令:nohup bash scripts &

>>>不会有标准输出和标准错误输出,而将输出追加式重定向到nohup.out 文件中(输出追加到此文件中,不删除原来的内容)

>>>nohup bash scripts> myout.file 2>&1 &             #重定向到指定文件

案例

[bei@localhost test]$ cat signal.sh
#!/bin/bash
count=1
while [ $count -le 5 ]
do
        echo "sleep $count"
        sleep $count
        count=$[ $count + 1 ]
done
echo "end"
[bei@localhost test]$ nohup bash signal.sh  &
[1] 43155
[bei@localhost test]$ nohup: ignoring input and appending output to `nohup.out'


[bei@localhost test]$
[bei@localhost test]$ jobs
[1]+  Running                 nohup bash signal.sh &
[bei@localhost test]$
[1]+  Done                    nohup bash signal.sh
[bei@localhost test]$ ls -al ./nohup.out
-rw-------. 1 bei bei 88 Sep 25 21:26 ./nohup.out
[bei@localhost test]$ cat ./nohup.out
sleep 1
sleep 2
sleep 3
sleep 4
sleep 5
end

 


 

⑤作业控制

>>>作业控制:启动、停止、无条件终止以及恢复作业等功能

 

作业控制只查看作业

>>>可以使用jobs命令查看后台进程

[bei@localhost test]$ bash signal.sh
^Z
[1]+  Stopped                 bash signal.sh
[bei@localhost test]$ bash signal.sh &
[2] 43611
[bei@localhost test]$ jobs
[1]+  Stopped                 bash signal.sh
[2]-  Running                 bash signal.sh &

说明:

>>>对于作业[1]使用Ctrl+z挂起,在jobs中显示Stopped表示作业已经暂时挂起

>>>对于作业[2],使用在执行脚本命令后面加上&符号,使它在后台运行,在jobs中显示Running表示作业正在运行中

>>>作业号的右边有加号"+"和减号"-",带加号的作业表示默认作业,表示使用作业控制命令时,未在命令行上指定作业号则默认操作的是带加号的作业;带减号的作业是带加号的作业的备胎,比如kill掉作业[1],原来带减号的作业[2]的减号就变成了加号

 

jobs命令相关选项说明

参数

描述

-l

列出进程的PID和对应的作业号

-n

只列出上次shell发出的通知后改变状态的作业

-p

只列出作业的PID

-r

列出处于运行状态的作业

-s

列出处于暂停状态的作业

 

批量kill后台的正在运行的所有进程

a= `jobs -p`                                #将所有进程的PID赋予给变量a

for i in $a;do kill $i;done      #如果想要kill后台所有进程,包括stopped的进程,使用-9参数,无条件终止进程(慎用)

 

终止后台指定作业号的作业:kill %number    (建议用作业号的方式kill,不用PID的方式)

[bei@localhost test]$ jobs
[1]-  Stopped                 bash signal.sh
[2]+  Stopped                 bash signal.sh
[3]   Running                 bash signal.sh &
[bei@localhost test]$ kill %3
[bei@localhost test]$ jobs
[1]-  Stopped                 bash signal.sh
[2]+  Stopped                 bash signal.sh
[3]   Terminated              bash signal.sh

注意:可以输入命令 kill %

不指定作业号,则kill的作业是带加号的作业

 

作业控制之重启停止的作业

>>>fg命令:将后台进程调至前台运行

fg number            (如果不加number,默认操作的是有+的作业)

案例

[bei@localhost test]$ cat signal.sh
#!/bin/bash
count=1
while [ $count -le 5 ]
do
        echo "$count second sleep"
        sleep 1
        count=$[ $count + 1 ]
done
echo "End"
[bei@localhost test]$ bash signal.sh
1 second sleep
2 second sleep
3 second sleep
^Z
[1]+  Stopped                 bash signal.sh
[bei@localhost test]$ fg 1
bash signal.sh
4 second sleep
5 second sleep
End

 

>>>bg命令:将挂起的进程在后台启动为运行状态:

bg number    (如果不加number,默认操作的是有+的作业

案例

[bei@localhost test]$ bash signal.sh
1 second sleep
^Z
[1]+  Stopped                 bash signal.sh
[bei@localhost test]$ bg 1
[1]+ bash signal.sh &
[bei@localhost test]$ 2 second sleep
3 second sleep
jobs
[1]+  Running                 bash signal.sh &   #输入jobs查看到作业正在后台运行,输出在屏幕上
[bei@localhost test]$ 4 second sleep
5 second sleep
End

[1]+  Done                    bash signal.sh

 

 


 

说明:

>>>以上内容是本人学习的总结

>>>如还有错误,请留言,指正

>>>亦可分享自己的想法,互相学习

你可能感兴趣的:(Linux,shell编程)