处理信号
Linux通过信号在不同进程之间通信。Linux编程时可能遇到的常见信号如下:
信号 |
值 |
描述 |
1 |
SIGHUP |
挂起进程 |
2 |
SIGINT |
终止进程 |
3 |
SIGQUIT |
停止进程 |
9 |
SIGKILL |
无条件终止进程 |
15 |
SIGTERM |
可能的话终止进程 |
17 |
SIGSTOP |
无条件停止但不终止进程 |
18 |
SIGTSTP |
停止或暂停但不终止进程 |
19 |
SIGCONT |
继续执行停止的进程 |
1 信号的捕捉
trap命令用来指定shell需要捕捉哪些Linux信号,以及如何处理这些信号。格式如下:
trap commands signals
不同的signal之间用空格隔开,commands表示如何处理signals。
如下示例脚本:
#! /bin/bash # testing signal trapping # trap "echo sorry, I have trapped Ctrl-C" SIGINT SIGTERM echo "Running..." count=1 while [ $count -le 10 ] do echo "Loop $count" sleep 5 count=$[ $count + 1 ] done echo "Ending..."
上述脚本在每次检测到SIGINT或者SIGTERM信号时,简单地显示一行信息,然后继续向下执行,而并不会终止程序。
如果trap命令的signals部分变为”EXIT”会如何呢?此时无论脚本是否正常退出,shell都会在程序终止时执行commands部分:
#! /bin/bash # trapping the script exit # trap "echo Byebye" EXIT echo "Running..." count=1 while [ $count -le 10 ] do echo "Loop $count" sleep 5 count=$[ $count + 1 ] done echo "Ending..."
2 移除捕捉
使用单破折号-移除已设定的捕捉信号,格式如下:
trap - EXIT
#! /bin/bash # removing a set trap # trap "echo Byebye" EXIT count=1 while [ $count -le 5 ] do echo "Loop $count" sleep 2 count=$[ $count + 1 ] done trap - EXIT echo "You won‘t see Byebye"
后台模式运行脚本
想在命令行中以后台模式运行shell脚本,只需要在执行命令后加上&符号就可以了:
[1]表示shell分配给后台进程的作业号,2296表示进程ID。当后台进程结束时,在终端上显示[1]+ Done ./33.sh,表示使用./33.sh命令运行的后台作业1已经Done。
可以使用ps命令查看当前运行的所有进程相关信息。
非控制台下运行脚本
由于每个后台进程都必须绑定到某个会话终端上,比如pts/0,那么如果会话退出时,后台进程自然就会被终止。可是有时候我们希望后台进程终端会话退出时继续执行,此时,需要使用nohup命令。由于nohup命令解除了进程与终端的关联,因此也就丢失了进程到STDOUT和STDERR的链接,而是将运行产生的输出信息保存到nohup.out文件中。
注:
nohup.out文件包含了通常发送到终端上的所有输出信息,多个后台进程的输出是被追加到nohup.out文件中的。
作业控制
作业控制一般包括启动、暂停、恢复、终止等。
1 查看命令jobs
jobs命令用于查看当前shell正在处理的作业:
#! /bin/bash # testing jobs command # echo "This is a test program $$" count=1 while [ $count -le 10 ] do echo "Loop $count" sleep 5 count=$[ $count + 1 ] done echo "This is the end of program"
作业后的+号表示当前默认的作业,带-号的作业在+号运行完成后自动成为默认作业。任何时候只有一个带+号和带-号的作业,不论当前shell中有多少作业正在运行。
jobs的命令参数:
参数 |
说明 |
-l |
列出进程的ID及其作业号 |
-n |
列出上次shell操作后状态改变的作业 |
-p |
列出作业的PID |
-r |
列出运行中的作业 |
-s |
列出已停止的作业 |
2 重启命令fg/bg
fg/bg + 作业号即可以前台模式/后台模式重启一个作业。
调整谦让度
在多任务操作系统中,内核将CPU时间片轮流分配给每个进程。默认情况下,从shell启动的所有进程在Linux系统中都有同样的调度优先级(scheduling priority)。调度优先级从-20[最高]~20[最低],默认情况下,bash shell以优先级0启动所有进程。
改变优先级可以使用两个命令:nice和renice,参数为-n,renice可以指定不同进程的优先级。二者都只能降低优先级,如果想提升当前优先级,必须使用root用户。
定时运行作业
1 at命令
at命令将作业提交到队列中,指定shell何时运行该作业。at的守护进程atd以后台模式来检查作业队列中的情况,多数Linux发行版在启动时就会运行atd进程。
atd守护进程检查系统中的特殊目录(/var/spool/at)来获取使用at命令提交的作业,默认情况下,每隔60s检查一次。如果队列中存在作业,atd进程检查作业设置的运行时间,在与当前时间匹配的情况下,atd进程运行此作业。
1.1 at命令的基本格式
at [-f filename] time
filename指定脚本文件名,time指定了shell何时运行该作业。针对不同的作业的优先级,存在26种不同的作业队列,用字母a~z来表示,字母排序越高,其优先级就越低。
1.2 作业相关信息
当作业在Linux上运行时,没有终端会关联到该作业,而是将STDOUT和STDERR输出以邮件形式发送给提交作业的用户:
atq命令用于列出系统中处于等待状态的作业:
可以通过atrm命令删除等待中的作业:atrm + 作业号:
2 cron程序
Linux使用cron程序来执行定期计划,cron在后台检查cron时间表来获得计划运行的作业。cron时间表采用如下格式指定作业的运行时间:
min hour dayofmonth month dayofweek command
cron时间表允许使用特定值、范围、通配符来指定条目。
如每天10:15运行一个命令,cron时间表条目如下:
15 10 * * * command
可以使用文本值(mon/tue/wed/thu/fri/sat/sun)或数值(0~6表示周日~周六)指定dayofweek。
可以使用crontab -l/-e检查/编辑当前cron时间表。
Linux系统中预配置的cron目录有如下4个:daily、hourly、monthly、weekly。
如果需要将某个脚本每天都执行一次,将其放到daily目录下即可。
当然,如果想比较精确地控制脚本的执行时间,还是需要手动编辑cron时间表。
注:
cron程序假定Linux系统一直处于运行状态,一旦中途关机,再次开机后便丢失了未完成的计划;取而代之的值anacron程序,anacron可以在再次开机时继续执行未完成的任务。anacron程序只会处理位于cron目录中的脚本,anacron时间表的格式如下:
period delay identifier command
period:以天为单位,指定作业多久运行一次;
delay:指定系统启动多长时间后anacron开始执行错过的脚本;
identifier:识别信息;
command:包含run-parts和cron脚本目录名[run-parts程序负责运行目录中的脚本]。
启动时运行
1 开机时运行脚本
启动Linux系统时,加载Linux内核到内存中,开始执行init过程:读取/etc/initab文件来找出当前系统的运行级别,该文件内容如下:
如上表示当前默认的运行级别为5,接着进入/etc/rc.d目录:
接着进入rc5.d目录,该目录中存放的是级别5下需要开机运行的程序。
以上是系统中默认的开机启动程序,如果想使得自己的脚本开机时启动,最好与系统程序独立开来。Linux系统提供了专门的文件来添加用户开机脚本,在centos中为:/etc/rc.d/rc.local文件,内容如下:
在该文件中,可以指定特定命令、语句、或者需要开机时启动的脚本[该脚本必须采用全路径描述]。
2 启动新的shell时运行脚本
每个用户的主目录中都有两个文件,bash shell用这两个文件来启动脚本并设置环境变量:
.bash_profile文件和.bashrc文件。
当通过系统登录启动新shell时,bash shell运行.bash_profile文件,因此任何登录时需要执行的脚本放到该文件中;
当通过运行bash程序启动新shell(包括新的终端登录)时,bash shell运行.bashrc文件,该文件内容如下: