一、处理信号
linux通过信号与系统中的进程通信。可以通过对脚本编程,使其在收到特定信号时执行某些命令。从而控制shell脚本的操作。
1.1 linux信号
linux系统和应用程序可以产生超过30个信号。下面列出最常见的linux系统信号:
信 号 | 值 | 描 述 |
---|---|---|
1 | SIGHUP | 挂起(hang up)进程 |
2 | SIGINT | 中断(interrupt)进程 |
3 | SIGQUIT | 停止(stop)进程 |
9 | SIGKILL | 无条件终止(terminate)进程 |
15 | SIGTERM | 尽可能终止进程 |
18 | SIGCONT | 继续运行停止的进程 |
19 | SIGSTOP | 无条件停止,但不终止进程 |
20 | SIGTSTP | 停止或暂停(pause),但不终止进程 |
默认情况下,bash shell会忽略SIGQUIT和SIGTERM信号。但是bash shell会处理收到的所有SIGHUP和SIGINT信号。
1.2 产生信号
bash shell 允许使用键盘组合键生成两种基本的linux信号。这个特性在需要停止或暂停失控脚本时非常方便。
1.2.1 中断进程
Ctrl+C 组合键生成SIGINT信号。
$ sleep 60
^C
$
1.2.2 暂停进程
Ctrl+Z 组合键生成SIGHUP信号
$ sleep 60
^Z
[1]+ Stopped sleep 60
方括号中的数字是作业号。shell将运行的各个进程称为作业,并为其分配在当前shell内唯一的作业号。
作业号从1开始,然后是2,依次递增。
$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 18307 4192051 0 80 0 - 2170 do_wai pts/15 00:00:00 bash
0 T 1000 208634 18307 0 80 0 - 1369 do_sig pts/15 00:00:00 sleep
0 R 1000 208849 18307 0 80 0 - 2202 - pts/15 00:00:00 ps
第2行第2列 T 表示sleep命令已暂停。
1.2.3 终止进程
可以使用kill命令向进程发送SIGKILL(9)信号
kill -9 pid
pid 可以通过ps命令查看
1.3 捕获信号
trap命令可以指定shell脚本需要侦测并处理的linux信号。如果脚本收到了trap命令中列出的信号,
则该信号不在由shell处理,而是由本地处理。
trap command signals
#!/usr/bin/bash
trap "echo I have trap Ctrl+C" SIGINT
echo this is a test script
count=1
while [ $count -le 10 ]
do
echo "loop #$count"
sleep 1
count=$[ $count+1 ]
done
#在bash shell中执行脚本
$ ./test.sh
this is a test script
loop #1
loop #2
loop #3
^CI have trap Ctrl+C
loop #4
loop #5
loop #6
^CI have trap Ctrl+C
loop #7
loop #8
loop #9
loop #10
1.4 获取脚本退出
除了在shell脚本中捕获信号,也可以在shell脚本退出时捕获信号。
这是在shell完成任务时执行命令的一种简便方法。
#!/usr/bin/bash
trap "echo bye bye" EXIT
echo this is a test script
count=1
while [ $count -le 5 ]
do
echo "loop #$count"
sleep 1
count=$[ $count+1 ]
done
#在bash shell中执行脚本
$ ./test.sh
this is a test script
loop #1
loop #2
loop #3
loop #4
loop #5
bye bye
1.5 修改信号
要想在脚本中的不同位置进行不同的信号捕获处理,只需重新使用带有新选项的trap命令即可。
#!/usr/bin/bash
trap "echo old trap command" SIGINT
echo this is a test script
count=1
while [ $count -le 3 ]
do
echo "loop #$count"
sleep 1
count=$[ $count+1 ]
done
trap "echo new trap command" SIGINT
count=1
while [ $count -le 3 ]
do
echo "loop #$count"
sleep 1
count=$[ $count+1 ]
done
#在bash shell中执行脚本
$ ./test.sh
this is a test script
loop #1
loop #2
^Cold trap command
loop #3
loop #1
^Cnew trap command
loop #2
loop #3
1.6 移除信号
想要移除信号,在trap命令与希望恢复默认行为的信号列表之间加上连字符(–)即可。
trap – signals
二、以后台模式运行脚本
2.1 后台运行脚本
以后台运行脚本非常简单,只需在脚本名后面加上 & 即可。
脚本名 &
$ ./test.sh &
[1] 229686
方括号内是作业号,后面跟的是PID。
三、在非控制台下运行脚本
有时候即便是退出了终端会话,也想在终端会话中启动shell脚本,让脚本一直以后台模式运行到结束。
这个是使用nohup命令实现的。
nohup命令能阻断发给特定进程的SIGHUP信号。当退出终端会话时,可以避免进程退出。
nohup命令格式:
nohup command
$ nohup ./test.sh &
[1] 233484
nohup: ignoring input and appending output to 'nohup.out'
由于nohup命令会解除终端和进程的关联,因此不再同STDOUT和STDERR绑定在一起。
为了保存该命令产生的输出,nohup命令会自动将STDOUT和STDERR产生的消息重定向到
一个名为 nohup.out 的文件中
nohup.out 文件一般会在当前工作目录创建,否则会在$HOME目录中创建
四、作业控制
4.1 查看作业
jobs命令允许用户查看shell正在处理的作业:
jobs
[1]+ Done nohup ./test.sh
选 项 | 描 述 |
---|---|
-l | 列出进程的PID及作业号 |
-n | 只列出上次shell发出通知后状态发生状态的作业 |
-p | 只列出作业的PID |
-r | 只列出运行中的作业 |
-s | 只列出已停止的作业 |
4.2 重启已停止的作业
在bash 作业控制中,可以将已停止的作业作为后台或前台进程重启。
bg 作业号 #以后台模式重启作业
fg 作业号 #以前台模式重启作业