实验环境:RHEL5.8 32Bit
bash脚本编程之十四 信号捕捉及系统管理之任务计划
·cross compile交叉编译
一般情况下我们在x86平台上编译好的二进制程序是没法拿到其他平台上面去运行的,交叉编译指的是在宿主机上面编译的二进制程序的格式不是按照宿主机的平台格式编译的,而是按照目标系统的平台格式进行编译的,即用A平台来编译非A平台的二级制程序的方式叫做交叉编译,我们的内核也可以实现交叉编译,用法:make ARCH=...。
·脚本变量知识点
1,变量赋值
bash脚本不需要在编写程序之前就声明变量及给变量赋值,因为bash脚本是一个动态类型的语言。
2,->${parameter:-word}
这种方法经常会用
表示如果变量parameter为空或未定义,则该变量的值展开为word,但是不会改变parameter的值,parameter的值仍然为空;否则就展开为parameter的值:
->${parameter:+word}
表示parameter的值为空或未定义,则不作任何操作;否则该变量的值展开为word:
->${parameter:=word}
表示如果parameter的值为空或未定义,则变量的值展开为word,并将展开后的值赋给parameter:
->${parameter:offset}
表示字符串切片,取子串,从offset处的后一个字符开始全部切片:
->${parameter:offset:length}
表示字符串切片,取子串,从offset处的后一个字符开始,取长度为length的子串:
3,如何让脚本使用配置文件
红帽系列的操作系统的/etc/rc.d/init.d目录下都有一堆系统的服务脚本:
而且这些服务脚本都有各自的配置文件,这些配置文件一般都在/etc/sysconfig目录下并且是和服务脚本同名的:
[ -n "$TEST" ]:
-n选项表示如果TEST变量的值不为空
如果变量的内容为字符串的时候,我们在处理的时候一般给变量两边加上引号。
4,函数中的变量和全局变量
如果函数中的变量名和全局变量重名的话,我们可以将函数中的变量名声明为本地变量:
方法:local VAR_NAME
如果重名的话会出现如下的问题
#!/bin/bash # a=1 # test() { a=$[3+4] } # test # for I in `seq $a 10`;do echo $I done #
脚本执行结果:
我们加上local关键字之后,本地变量就只能在函数内部生效,脚本整体也会正常:
#!/bin/bash # a=1 # test() { local a=$[3+4] } # test # for I in `seq $a 10`;do echo $I done #
脚本执行结果:
·mktemp命令
该命令用于创建临时文件或目录。
用法:mktemp /tmp/file.XX,使用这种方法创建的临时文件永远不会重名,这是mktemp这个命令的机制决定的:
-d选项,表示创建临时目录:
在tmp目录下存放的所有文件都会定期被删除,每隔30天会做一次清理,将30天内再也没有被访问过的文件进行删除。
·信号
信号是进程间相互通信的方式,是一个进程向另一个进程发送的短小的消息,实现控制另外一个进程运作法则的运作机制,通常我们使用kill命令来发送信号,用法:
kill -SINGAL 进程PID
SINGAL:
1,1号SIGHUP
2,2号SIGINT(interrupt->中断信号)
3,9号SIGKILL
4,15号SIGTERM
我们在脚本中也可以实现信号的捕捉,这个时候就要使用trap命令,但是9号和15号信号无法捕捉,快捷键Ctrl+C发送的是2号信号SIGINT。
·trap命令
trap命令是bash的一个內建命令,用于实现信号的捕捉。
用法:trap 'COMMAND' 信号列表
#!/bin/bash # trap 'echo "You go...Im not go!"' INT # while :; date sleep 2 done #
脚本执行结果:
快捷键Ctrl+Z发送的是SIGSTOP(stop)信号,bg命令发送的是SIGCONT(continue)信号,trap命令不允许捕捉9号和15号信号。
有时候我们在执行脚本的过程中会产生很多的垃圾文件,如果我们在脚本的执行过程中使用Ctrl+C中断脚本的执行的话,这些垃圾文件就会滞留在我们的系统当中成为垃圾,这个时候我们可以在脚本当中使用trap命令来解决这个问题:
脚本内容如下:
#!/bin/bash # NET=10.245.6 # FILE=`mktemp /tmp/file.XXXXX` # clearup() { echo "quit..." rm -fr $FILE exit 1 } # trap 'clearup' INT # for I in `seq 1 10`;do if ping -c 1 -W 1 $NET.$I &> /dev/null;then echo $NET.$I is up | tee $FILE else echo $NET.$I is down fi done #
脚本执行结果:
·任务计划
很多时候我们在编写了一个系统服务脚本之后,我们不希望该脚本可以立即执行,而是希望该脚本在未来的某一个时间开始执行,这就叫做任务计划,任务计划分为两类:
1,在未来的某个时间点只执行一次某任务
使用at命令即可实现
用法:at 时间点(未来的时间)
当我们按下回车后,bash会返回给我们一个at命令的提示符,我们在该提示符下键入我们想要执行的命令,使用快捷键Ctrl+D提交任务即可:
at命令指定时间的方法:
->at HH:MM|DD.MM.YY|MM/DD/YY(绝对时间)
->at now+#(相对时间)
相对时间的单位:minutes,hours,days,weeks
->模糊时间
at noon(正午12点)
at midnight(半夜12点)
at teatime(下午4点)
at命令的执行结果将以邮件的方式发送给安排任务的用户。
查看at命令任务列表的命令:
->at -l=atq
该命令可以显示用户自己的作业列表:
该命令一共显示四个字段分别为:
⑴第几个作业任务
⑵作业任务的执行时间
⑶作业任务的队列(队列是用来给作业任务分类的,队列只能用一个单个字符来表示,默认情况下都是a)
⑷安排任务的用户
->at -d=atrm
该命令用于删除作业任务
用法:at -d 作业号=atrm
/etc/at.deny和/etc/at.allow这两个文件分别为at命令使用者的白名单和黑名单,黑名单中的用户无法使用at命令,白名单中的用户则可以使用at命令:
如果白名单和黑名单都存在,那么就只有白名单生效:
如果黑名单和白名单都不存在,那么就只有root用户可以使用at命令:
除了at命令还可以使用batch命令
batch命令也是在未来的某一时间点将我们制定的任务执行一次,但是batch命令不需要指定时间,它会自动在我们系统比较空闲的时候去执行任务计划,这个命令当做了解即可。
2,周期性的执行任务计划
要想完称周期性的执行性任务计划的方式,必须以服务的形式不停的监控某些脚本或者某些任务的执行情况,这个时候我们必须以服务的形式来实现,这个服务就叫做cron,cron任务分为两大类:
⑴系统cron任务
系统cron任务是和用户没有关系的cron任务,是我们的操作系统自身为了周期性的维护某一个操作或某些任务而专门安排的,比如系统会定期清楚/tmp目录下的内容,比如updatedb命令等等,系统的cron任务一般都定义在/etc/crontab文件中:
由上图可知,该文件中提供的run-parts命令是红帽系列操作系统所提供的一个脚本,该脚本可以接收一个参数,接受的所有参数都是目录,该命令表示将传递的目录参数下的脚本和命令在定义的时间全部执行一次,但是这些脚本不可能同时执行,所以run-parts命令可以让这些目录下的脚本全部按照名称的排列顺序来依次执行:
如果用户想让哪些脚本的执行顺序靠前,在脚本的名称前面加上数字即可,数字越小排序越靠前,系统的cron任务和用户的cron任务的格式是不同的,这是因为每一个任务计划运行起来可能是一个进程也可能是多个进程,而每一个进程都是依靠一个用户的身份去运行的,系统cron任务有7个字段:
分别是:
分钟 小时 天 月 周 发起任务的用户 所要执行的任务
表示时间的字段总共有5个,每个字段的有效取值范围:
分钟->0-59
小时->0-23
天->1-31
月->1-12
周->0-7(0和7都表示周日)
时间字段的通配表示法:
⑴*:表示对应时间的所有有效取值
3 * * * *表示每小时的第三分钟
3 * * * 7表示每周日的每小时的第三分钟
13 12 * * *表示每天的12点13分
13 12 * * 5表示每周五的12点13分
13 12 6 * *表示每个月的6号的12点13分
13 12 6 * 3表示每个月的6号而且这一天还必须是周三的12点13分
这样设置cron任务会很麻烦,所以我们一般每月的几号和每周几不会重复使用。
⑵,:表示离散时间点取值
10,40 * * * *表示每小时的第10分钟和第40分钟
10,40 * * * 2,5表示每周二和每周五的每小时的第10分钟和第40分钟
10,40 2 * * 2,5表示每周五和每周二的2:10和2:40
⑶-:表示连续时间取值
10 02 * * 1-5表示每周一到五的2:10
⑷/:表示对应取值范围内每多久一次
用法:/#(#表示频率)
*/3 * * * *表示每三分钟一次
4 */2 * * *表示每两小时一次
当我们指定的是每一个时间点的时候,比它小的时间点一定要给一个具体的值。
4 4 */2 * *表示每两天一次
cron任务的执行结果和at命令的执行结果一样,都会以邮件的形式发送给管理员。
cron的环境变量,cron任务中所执行的命令也得到我们的path环境变量中去查找,但是有些命令的我们的用户成功登录系统之后,才可以查找的到,所以我们在cron任务中使用的命令都得使用命令的绝对路径,如果是脚本中的cron任务的话,我们可以在脚本内部定义脚本自身的环境变量:
⑵用户的cron任务
用户的cron任务一般都定义在/var/spool/cron/$USERNAME这个文件当中,每一个用户都有一个和自己用户名相对应的文件,用户的cron任务有6个字段:
5个字段代表时间,一个字段代表所要执行的任务,不需要再指定发起任务的用户,因此系统cron任务和用户cron任务是不同的,不过二者的字段与字段之间都是以空格隔开的,用户cron任务的管理是依靠crontab命令来实现的:
-l选项表示列出当前用户的cron任务
-e选项表示自定义任务
-r选项表示移除所有任务
-u USERNAME选项表示管理其他用户的cron任务
anacron:
anacron是对cron的补充,能够让cron去执行那些因为各种原因在过去的时间该执行而未执行的任务,在系统恢复正常后再执行一次,如果cron是运行在一个长时间不会关机的服务器上的时候那么我们就不再需要anacron了,anacron本身也必须随时在线执行(指的是anacron服务必须开启),一般情况下我们只有在那些经常需要关机的机器上才会启动anacron服务,anacron的配置文件是/etc/anacrontab:
anacron任务一共有四个字段:
->第一个字段的单位是天,表示有#天没有执行该任务了
->第二个字段的单位是分钟,表示开机之后的第#分钟开始执行该任务
->第三个字段是纯注释信息
->第四个字段表示的是所要执行的任务
无论是cron任务还是anacron任务想要正确执行,必须开启crond和anacron服务,只有这两个服务处于运行状态,cron和anacron任务才可以正确执行:
这两个服务同样受到chkconfig的控制:
由上图可知,这两个服务在2345运行级别下默认是开机自启动的。