Linux命令行-第16章@shell编程-控制脚本③定时运行作业

490 篇文章 10 订阅
394 篇文章 2 订阅

第 16章 控制脚本

在这里插入图片描述

本章内容
 处理信号
 以后台模式运行脚本
 禁止挂起
 作业控制
 修改脚本优先级
 脚本执行自动化

开始构建高级脚本时,你大概会问如何在Linux系统上运行和控制它们。在本书中,到当目前为止,我们运行脚本的唯一方式就是以实时模式在命令行界面上直接运行。这并不是Linux上运行脚本的唯一方式。有不少方法可以用来运行shell脚本。另外还有一些选项能够用于控制脚本。这些控制方法包括向脚本发送信号、修改脚本的优先级以及在脚本运行时切换到运行模式。本章将会对逐一介绍这些方法。

16.6 定时运行作业

当你开始使用脚本时,可能会想要在某个预设时间运行脚本,这通常是在你不在场的时候。Linux系统提供了多个在预选时间运行脚本的方法:at命令和cron表。每个方法都使用不同的技术来安排脚本的运行时间和频率。接下来会依次介绍这些方法。
在这里插入图片描述

16.6.1 用at命令来计划执行作业

at命令允许指定Linux系统何时运行脚本。at命令会将作业提交到队列中,指定shell何时运行该作业。at的守护进程atd会以后台模式运行,检查作业队列来运行作业。大多数Linux发行版会在启动时运行此守护进程。
atd守护进程会检查系统上的一个特殊目录(通常位于/var/spool/at)来获取用at命令提交的作业。默认情况下,atd守护进程会每60秒检查一下这个目录。有作业时,atd守护进程会检查作业设置运行的时间。如果时间跟当前时间匹配,atd守护进程就会运行此作业。
后面几节会介绍如何用at命令提交要运行的作业以及如何管理这些作业。
1. at命令的格式
at命令的基本格式非常简单:

at [-f filename] time 

默认情况下,at命令会将STDIN的输入放到队列中。你可以用-f参数来指定用于读取命令(脚本文件)的文件名。
time参数指定了Linux系统何时运行该作业。如果你指定的时间已经错过,at命令会在第二天的那个时间运行指定的作业。
在如何指定时间这个问题上,你可以非常灵活。at命令能识别多种不同的时间格式。
 标准的小时和分钟格式,比如10:15。
 AM/PM指示符,比如10:15 PM。
 特定可命名时间,比如now、noon、midnight或者teatime(4 PM)。
除了指定运行作业的时间,也可以通过不同的日期格式指定特定的日期。
 标准日期格式,比如MMDDYY、MM/DD/YY或DD.MM.YY。
 文本日期,比如Jul 4或Dec 25,加不加年份均可。
 你也可以指定时间增量。
 当前时间+25 min
 明天10:15 PM
 10:15+7天
在你使用at命令时,该作业会被提交到作业队列(job queue)。作业队列会保存通过at命令提交的待处理的作业。针对不同优先级,存在26种不同的作业队列。作业队列通常用小写字母az和大写字母AZ来指代。

说明 在几年前,也可以使用batch命令在指定时间执行某个脚本。batch命令很特别,你可以安排脚本在系统处于低负载时运行。但现在batch命令只不过是一个脚本而已(/usr/bin/batch),它会调用at命令并将作业提交到b队列中。
作业队列的字母排序越高,作业运行的优先级就越低(更高的nice值)。默认情况下,at的作业会被提交到a作业队列。如果想以更高优先级运行作业,可以用-q参数指定不同的队列字母。
2. 获取作业的输出
当作业在Linux系统上运行时,显示器并不会关联到该作业。取而代之的是,Linux系统会将提交该作业的用户的电子邮件地址作为STDOUT和STDERR。任何发到STDOUT或STDERR的输出都会通过邮件系统发送给该用户。
这里有个在CentOS发行版中使用at命令安排作业执行的例子。

$ cat test13.sh 
#!/bin/bash 
# Test using at command 
# 
echo "This script ran at $(date +%B%d,%T)" echo 
sleep 5 
echo "This is the script's end..." 
# 
$ at -f test13.sh now 
job 7 at 2015-07-14 12:38 
$ 

at命令会显示分配给作业的作业号以及为作业安排的运行时间。-f选项指明使用哪个脚本文件,now指示at命令立刻执行该脚本。
使用e-mail作为at命令的输出极其不便。at命令利用sendmail应用程序来发送邮件。如果你的系统中没有安装sendmail,那就无法获得任何输出!因此在使用at命令时,最好在脚本中对STDOUT和STDERR进行重定向(参见第15章),如下例所示。

$ cat test13b.sh 
#!/bin/bash 
# Test using at command 
# 
echo "This script ran at $(date +%B%d,%T)" > test13b.out echo >> test13b.out 
sleep 5 
echo "This is the script's end..." >> test13b.out 
# 
$ 
$ at -M -f test13b.sh now 
job 8 at 2015-07-14 12:48 
$ 
$ cat test13b.out 
This script ran at July14,12:48:18 
This is the script's end... 
$ 

如果不想在at命令中使用邮件或重定向,最好加上-M选项来屏蔽作业产生的输出信息。
3. 列出等待的作业
atq命令可以查看系统中有哪些作业在等待。

$ at -M -f test13b.sh teatime 
job 17 at 2015-07-14 16:00 
$ 
$ at -M -f test13b.sh tomorrow 
job 18 at 2015-07-15 13:03 
$ 
$ at -M -f test13b.sh 13:30 
job 19 at 2015-07-14 13:30 
$ 
$ at -M -f test13b.sh now 
job 20 at 2015-07-14 13:03 
$ 
$ atq 
20      2015-07-14 13:03 = Christine 18      2015-07-15 13:03 a Christine 17      2015-07-14 16:00 a Christine 19      2015-07-14 13:30 a Christine $ 

作业列表中显示了作业号、系统运行该作业的日期和时间及其所在的作业队列。
4. 删除作业
一旦知道了哪些作业在作业队列中等待,就能用atrm命令来删除等待中的作业。

$ atq 
18      2015-07-15 13:03 a Christine 17      2015-07-14 16:00 a Christine 19      2015-07-14 13:30 a Christine $ 
$ atrm 18 
$ 
$ atq 
17      2015-07-14 16:00 a Christine 19      2015-07-14 13:30 a Christine $ 

只要指定想要删除的作业号就行了。只能删除你提交的作业,不能删除其他人的。

16.6.2 安排需要定期执行的脚本

用at命令在预设时间安排脚本执行非常好用,但如果你需要脚本在每天的同一时间运行或是每周一次、每月一次呢?用不着再使用at不断提交作业了,你可以利用Linux系统的另一个功能。
Linux系统使用cron程序来安排要定期执行的作业。cron程序会在后台运行并检查一个特殊的表(被称作cron时间表),以获知已安排执行的作业。
1. cron时间表
cron时间表采用一种特别的格式来指定作业何时运行。其格式如下:

min hour dayofmonth month dayofweek command 

cron时间表允许你用特定值、取值范围(比如1~5)或者是通配符(星号)来指定条目。例如,如果想在每天的10:15运行一个命令,可以用cron时间表条目:

15 10 * * * command 

在dayofmonth、month以及dayofweek字段中使用了通配符,表明cron会在每个月每天的10:15执行该命令。要指定在每周一4:15 PM运行的命令,可以用下面的条目:

15 16 * * 1 command 

可以用三字符的文本值(mon、tue、wed、thu、fri、sat、sun)或数值(0为周日,6为周六)来指定dayofweek表项。
这里还有另外一个例子:在每个月的第一天中午12点执行命令。可以用下面的格式:

00 12 1 * * command 

dayofmonth表项指定月份中的日期值(1~31)。
说明 聪明的读者可能会问如何设置一个在每个月的最后一天执行的命令,因为你无法设置
dayofmonth的值来涵盖所有的月份。这个问题困扰着Linux和Unix程序员,也激发了不少解决办法。常用的方法是加一条使用date命令的if-then语句来检查明天的日期是不是01:

00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command 

它会在每天中午12点来检查是不是当月的最后一天,如果是,cron将会运行该命令。
命令列表必须指定要运行的命令或脚本的全路径名。你可以像在普通的命令行中那样,添加任何想要的命令行参数和重定向符号。

15 10 * * * /home/rich/test4.sh > test4out 

cron程序会用提交作业的用户账户运行该脚本。因此,你必须有访问该命令和命令中指定的输出文件的权限。
2. 构建cron时间表
每个系统用户(包括root用户)都可以用自己的cron时间表来运行安排好的任务。Linux提供了crontab命令来处理cron时间表。要列出已有的cron时间表,可以用-l选项。

$ crontab -l 
no crontab for rich 
$ 

默认情况下,用户的cron时间表文件并不存在。要为cron时间表添加条目,可以用-e选项。在添加条目时,crontab命令会启用一个文本编辑器(参见第10章),使用已有的cron时间表作为文件内容(或者是一个空文件,如果时间表不存在的话)。
3. 浏览cron目录
如果你创建的脚本对精确的执行时间要求不高,用预配置的cron脚本目录会更方便。有4个基本目录:hourly、daily、monthly和weekly。

$ ls /etc/cron.*ly 
/etc/cron.daily: 
cups       makewhatis.cron  prelink         tmpwatch 
logrotate  mlocate.cron     readahead.cron  
/etc/cron.hourly: 
0anacron 
/etc/cron.monthly: 
readahead-monthly.cron 
/etc/cron.weekly: 
$ 

因此,如果脚本需要每天运行一次,只要将脚本复制到daily目录,cron就会每天执行它。
4. anacron程序
cron程序的唯一问题是它假定Linux系统是7×24小时运行的。除非将Linux当成服务器环境来运行,否则此假设未必成立。
如果某个作业在cron时间表中安排运行的时间已到,但这时候Linux系统处于关机状态,那么这个作业就不会被运行。当系统开机时,cron程序不会再去运行那些错过的作业。要解决这个问题,许多Linux发行版还包含了anacron程序。
如果anacron知道某个作业错过了执行时间,它会尽快运行该作业。这意味着如果Linux系统关机了几天,当它再次开机时,原定在关机期间运行的作业会自动运行。
这个功能常用于进行常规日志维护的脚本。如果系统在脚本应该运行的时间刚好关机,日志文件就不会被整理,可能会变很大。通过anacron,至少可以保证系统每次启动时整理日志文件。
anacron程序只会处理位于cron目录的程序,比如/etc/cron.monthly。它用时间戳来决定作业是否在正确的计划间隔内运行了。每个cron目录都有个时间戳文件,该文件位于/var/spool/ anacron。

$ sudo cat /var/spool/anacron/cron.monthly 20150626 
$ 

anacron程序使用自己的时间表(通常位于/etc/anacrontab)来检查作业目录。

$ sudo cat /etc/anacrontab 
# /etc/anacrontab: configuration file for anacron  
# See anacron(8) and anacrontab(5) for details. 

SHELL=/bin/sh 
PATH=/sbin:/bin:/usr/sbin:/usr/bin 
MAILTO=root 
# the maximal random delay added to the base delay of the jobs RANDOM_DELAY=45 
# the jobs will be started during the following hours only 
START_HOURS_RANGE=3-22 
#period in days   delay in minutes   job-identifier   command 
1       5       cron.daily              nice run-parts /etc/cron.daily 
7       25      cron.weekly             nice run-parts /etc/cron.weekly 
@monthly 45     cron.monthly            nice run-parts /etc/cron.monthly 
$ 

anacron时间表的基本格式和cron时间表略有不同:

period delay identifier command 

period条目定义了作业多久运行一次,以天为单位。anacron程序用此条目来检查作业的时间戳文件。delay条目会指定系统启动后anacron程序需要等待多少分钟再开始运行错过的脚本。command条目包含了run-parts程序和一个cron脚本目录名。run-parts程序负责运行目录中传给它的任何脚本。
注意,anacron不会运行位于/etc/cron.hourly的脚本。这是因为anacron程序不会处理执行时间需求小于一天的脚本。
identifier条目是一种特别的非空字符串,如cron-weekly。它用于唯一标识日志消息和错误邮件中的作业。

16.6.3 使用新shell启动脚本

如果每次运行脚本的时候都能够启动一个新的bash shell(即便只是某个用户启动了一个bash shell),将会非常的方便。有时候,你希望为shell会话设置某些shell功能,或者只是为了确保已经设置了某个文件。
回想一下当用户登入bash shell时需要运行的启动文件(参见第6章)。另外别忘了,不是所有的发行版中都包含这些启动文件。基本上,依照下列顺序所找到的第一个文件会被运行,其余的文件会被忽略:
 $HOME/.bash_profile
 $HOME/.bash_login
 $HOME/.profile
因此,应该将需要在登录时运行的脚本放在上面第一个文件中。
每次启动一个新shell时,bash shell都会运行.bashrc文件。可以这样来验证:在主目录下的.bashrc文件中加入一条简单的echo语句,然后启动一个新shell。

$ cat .bashrc # .bashrc 
# Source global definitions if [ -f /etc/bashrc ]; then         . /etc/bashrc 
fi 
# User specific aliases and functions echo "I'm in a new shell!" 
$ 
$ bash 
I'm in a new shell! 
$ 
$ exit exit 
$ 

.bashrc文件通常也是通过某个bash启动文件来运行的。因为.bashrc文件会运行两次:一次是当你登入bash shell时,另一次是当你启动一个bash shell时。如果你需要一个脚本在两个时刻都得以运行,可以把这个脚本放进该文件中。

16.7 小结

Linux系统允许利用信号来控制shell脚本。bash shell接受信号,并将它们传给运行在该shell进程中的所有进程。Linux信号允许轻松地终止一个失控进程或临时暂停一个长时间运行的进程。
可以在脚本中用trap语句来捕获信号并执行特定命令。这个功能提供了一种简单的方法来控制用户是否可以在脚本运行时中断脚本。
默认情况下,当你在终端会话shell中运行脚本时,交互式shell会挂起,直到脚本运行完。可以在命令名后加一个&符号来让脚本或命令以后台模式运行。当你在后台模式运行命令或脚本时,交互式shell会返回,允许你继续输入其他命令。任何通过这种方法运行的后台进程仍会绑定到该终端会话。如果退出了终端会话,后台进程也会退出。
可以用nohup命令阻止这种情况发生。该命令会拦截任何发给某个命令来停止其运行的信号
(比如当你退出终端会话时)。这样就可以让脚本继续在后台运行,即便是你已经退出了终端会话。
当你将进程置入后台时,仍然可以控制它的运行。jobs命令可以查看该shell会话启动的进程。只要知道后台进程的作业号,就可以用kill命令向该进程发送Linux信号,或者用fg命令将该进程带回到该shell会话的前台。你可以用Ctrl+Z组合键挂起正在运行的前台进程,然后用bg命令将
其置入后台模式。
nice命令和renice命令可以调整进程的优先级。通过降低进程的优先级,你可以让给该进
程分配更少的CPU时间。当运行需要消耗大量CPU时间的长期进程时,这一功能非常方便。
除了控制处于运行状态的进程,你还可以决定进程在系统上的启动时间。不用直接在命令行界面的提示符上运行脚本,你可以安排在另一个时间运行该进程。有几种不同的实现途径。at
命令允许你在预设的时间运行脚本。cron程序提供了定期运行脚本的接口。
最后,Linux系统提供了脚本文件,可以让你的脚本在用户启动一个新的bash shell时运行。与此类似,位于每个用户主目录中的启动文件(如.bashrc)提供了一个位置来存放新shell启动时
需要运行的脚本和命令。
下一章将学习如何编写脚本函数。脚本函数可以让你只编写一次代码,就能在脚本的不同位置中多次使用。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

华为奋斗者精神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值