1. 处理信号
Linux利用信号与运行在系统中的进程进行通信。
信号 值 描述
1 SIGHUP 挂起进程
2 SIGINT 终止进程
3 SIGQUIT 停止进程
9 SIGKILL 无条件终止进程
15 SIGTERM 尽可能终止进程
17 SIGSTOP 无条件停止进程,但不是终止进程
18 SIGTSTP 停止或暂停进程,但不终止进程
19 SIGCONT 继续运行停止的进程
默认情况下,bash shell会忽略收到的任何SIGQUIT(3)和SIGTERM(15)信号(正因为这样,交互式shell才不会被意外终止)。但是bash shell会处理收到的SIGHUP(1)和SIGINT(2)信号。
如果bash shell收到了SIGHUP信号,比如当你要离开一个交互式shell,它就会退出。但在退出之前,它会将SIGHUP信号传给所有由该shell所启动的进程(包括正在运行的shell脚本)。
通过SIGINT信号,可以中断shell。Linux内核会停止为shell分配CPU处理时间。这种情况发生时,shell会将SIGINT信号传给所有由它所启动的进程,以此告知出现的状况。
可以知道,shell会将这些信号传给shell脚本程序来处理。而shell脚本的默认行为是忽略这些信号。它们可能会不利于脚本的运行。要避免这种情况,你可以脚本中加入识别信号的代码,并执行命令来处理信号。
(1)生成信号
ctrl+c 会产生SIGINT信号,完全中断进程
ctrl+z 会残生SIGTSTP信号,停止进程,但是没有中断,可以通过kill命令来中断进程。使用kill必须带信号号数,比如:kill -9 2456 pid为2456的进程就中断了。
(2)捕获信号
也可以不忽略信号,在信号出现时捕获它们并执行其它命令。trap命令允许你来指定shell脚本要监看并从shell中拦截的Linux信号。如果脚本收到了trap命令中列出的信号,该信号不再由shell处理,而是交由本地处理。
trap commands signals
1 trap "echo 'sorry,I have trapped ctrl_c'" SIGINT 2 sleep 5 3 echo "hahah" 4 sleep 3 5 echo "hello" 6 [Hermioner@localhost Documents]$ bash test 7 ^Csorry,I have trapped ctrl_c #在sleep时按住了ctrl+c,这就发送了SIGINT信号 8 hahah 9 ^Csorry,I have trapped ctrl_c #在sleep时按住了ctrl+c,这就发送了SIGINT信号 10 hello 11 [Hermioner@localhost Documents]$
(3)移除捕获
trap -- signals
1 [Hermioner@localhost Documents]$ cat test 2 #!/bin/bash 3 trap "echo 'sorry,I have trapped ctrl_c'" SIGINT 4 sleep 5 5 echo "hahah" 6 trap -- SIGINT 7 sleep 3 8 echo "hello" 9 [Hermioner@localhost Documents]$ bash test 10 ^Csorry,I have trapped ctrl_c 11 hahah 12 ^C 13 [Hermioner@localhost Documents]$
2. 以后台模式运行脚本-----随着会话的结束而结束
在后台模式中,进程运行时不会和终端会话上的STDIN、STDOUT以及STDERR关联。允许它们在后台运行而不用占用终端会话,这样就可以在终端上做别的事情啦。
直接加入&就可以以后台模式运行shell脚本啦。
1 [Hermioner@localhost Documents]$ cat test 2 #!/bin/bash 3 sleep 3 4 echo "hello" 5 [Hermioner@localhost Documents]$ bash test & 6 [1] 4878 7 [Hermioner@localhost Documents]$ ls 8 a ltest test1 test2 test3 test8 testfile 9 atest test test1.sh test2.sh test3.sh test9 10 [Hermioner@localhost Documents]$ hello 11 ^C 12 [1]+ Done bash test 13 [Hermioner@localhost Documents]$ 14 15 16 在休眠时候,可以执行别的语句。当后台执行完毕,会自动输出到终端上面来,hello,并且需要按住ctrl+c才终止。
note1:可以在命令提示符下同时启动多个后台作业
note2:一旦会话退出,那么后台进程也会随之退出。
3. 在非控制台下运行脚本-------后台进程不会因为会话的结束而结束
采用nohup命令可以实现,它运行了另外一个命令来阻断所有发送给该进程的SIGHUP信号,这回在退出终端会话时阻止进程退出。
nohup ./test1.sh &
note1:由于nohup命令会解除终端与进程的关联,进程也就不再同STDOUT和STDERR联系在一起。为了保存该命令产生的输出,nohup命令会自动将STDOUT和STDERR的消息重定向到一个名为nohup.out的文件中。
4. 作业控制
启动、停止、终止以及恢复作业的这些功能称为作业控制。通过作业控制,就能完全控制shell环境中所有的进程的运行方式了。
(1)查看作业
jobs命令。允许查看当前正在处理的作业。
eg: $ jobs
[1] Running ./test9.sh
[1] + Stopped ./test10.sh
[2] - Running ./test10.sh > test10.out &
note:jobs命令输出中的加号和减号。带加号的作业会被当作默认作业。带减号的作业是下一个默认作业。任何时候都只有一个带加号和带减号的作业,不管 由多少个shell正在运行。
(2)重启停止的作业
可以将已经停止的作业作为后台进程或前台进程重启。后台用 bg 作业号 前台用 fg 作业号
5. 调整谦让度
在多任务操作系统中(Linux就是),内核负责将CPU时间分配给系统上运行的每个进程。调度优先级是内核分配给进程的CUP时间(相对于其它进程)。在Linux系统中,由shell启动的所有进程的调度优先级默认都是相同的。
调度优先级是个整数值,从-20(最高优先级)到+19(最低优先级)。默认情况下,bash shell以优先级0来启动所有进程。
nice -n 具体的数值 启动命令 eg: nice -n 4 ./test.sh
note:无法提高命令的优先级,只可以减小。
note2: renice命令也可以降低优先级,但是它可以更改已经运行的命令的优先级,它能够自动更新当前运行进程的调度的优先级。
6. 定时运行作业
可以采用at命令和cron表来定时运行作业。
(1)at
原理:at命令允许指定Linux系统何时运行脚本。at命令会将作业提交到队列中,指定shell何时运行该作业。at的守护进程atd会以后台模式运行,检查作 业队列来运行作业。大多数Linux发行版会在启动时运行此守护进程。atd守护进程会检查系统上的一个特殊目录(通常位于/var/spool/at)来获取at命令提交 的 作业。默认情况下,atd守护进程会每60秒检查一下这个目录。有作业时,atd守护进程会检查作业设置运行的时间。如果时间跟当前时间匹配,atd守护进 程就会运行此作业。 如果你指定的时间已经错误,at命令会在第二天的那个时候运行指定的作业。
格式: at [ -f filename] time
默认情况下,at命令会将STDIN的输入放到队列中。也可以添加-f参数来指定用于读取命令(脚本文件)的文件名。time的时间格式也支持很多种。
eg: at -f test12.sh now
缺点:at命令会自动使用sendmail应用程序来发送邮件,在邮件中的内容就是STDOUT和STDERR内容。因此还需要安装sendmail软件。因此,为避免,可以在脚 本中采用输出重定向,这样就不通过邮件将echo等语句输出放到邮件中了。也可以删除队列中等待的的作业。
(2) cron时间表
如果要脚本在每天的同一时间运行,或者每周一次等等,就不能使用at不断提交作业了,可以采用cron程序来安排要定期执行的作业。
格式: min hour dayofmonth month dayofweek command
eg: 15 10 * * * command 表面会在每个月每天的10:15执行该命令。
缺点,可能服务器关机了,停机的那些天的命令在开机后不会执行。为避免这个,可以采用anacron程序来执行之前因为关机未执行的程序。---------运维用的。
参考文献:
Linux命令行与shell脚本编程大全(第3版)[美] 布鲁姆(Richard Blum),布雷斯纳汉(Christine Bresnahan) 著,门佳,武海峰 译