①信号基础
②产生信号
③捕捉信号
④运行模式
后台运行脚本
非控制台下运行脚本
⑤作业控制
作业控制只查看作业
作业控制之重启停止的作业
fg命令
bg命令
>>>Linux系统上通过Linux信号可以实现对脚本的控制
>>>bash shell会忽略SIGQUIT(3)和SIGTERM(15)的信号,会处理SIGHUP(1)和SIGINT(2)的信号
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 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 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 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
说明:
>>>以上内容是本人学习的总结
>>>如还有错误,请留言,指正
>>>亦可分享自己的想法,互相学习