如何使用Cron,Anacron和命令安排Linux上的作业

时间:2020-03-05 15:29:23  来源:igfitidea点击:

作业调度是一个功能,允许用户在将来在指定时间提交命令或者程序以执行执行。
在Linux服务器上,重要的是,某些任务在某些时间运行的时间乘以命令或者程序的执行可能是一次或者基于预定的时间表定期。
例如,安排系统维护命令在非工作时间内运行是一个很好的做法,因为它不会破坏正常的业务活动。

了解工作计划

Linux基于是否定期发生:ATD和Crond有两个调度作业的守护进程。
Cron系统在预先指定的时间内重复运行就是每月,每周,每日,每小时或者甚至每分钟的次数运行作业,而AT系统用于作业计划在未来的一个时间,例如周末运行作业。
第三个系统,称为anacron与Cron密切相关的anacron用于运行可能并不总是像笔记本电脑的系统上运行定期作业。
在本文中,我将解释如何使用每个命令在Linux服务器上安排任务或者作业

1)使用Cron服务安排任务

当预计该系统预期诸如过夜时,我们通常会在时间安排密集的工作。
一个名为crond的守护程序在后台运行并检查其配置每分钟,以检查配置文件,以便在指示的时间匹配时间匹配时执行命令或者shell脚本。
在"/etc""下的一系列配置文件也可以包含作业和控制,用户可以使用CRONTAB添加作业。

# ls -ld /etc/cron*
drwxr-xr-x. 2 root root 4096 Aug 24 17:05 /etc/cron.d
drwxr-xr-x. 2 root root 4096 Aug 24 16:03 /etc/cron.daily
-rw-------. 1 root root 0 Mar 31 2015 /etc/cron.deny
drwxr-xr-x. 2 root root 4096 Jun 9 2014 /etc/cron.hourly
drwxr-xr-x. 2 root root 4096 Jun 9 2014 /etc/cron.monthly
-rw-r--r--. 1 root root 451 Jun 9 2014 /etc/crontab
drwxr-xr-x. 2 root root 4096 Jun 9 2014 /etc/cron.weekly

管理CRON服务很容易,因为不需要重新加载或者重新启动以激活对其配置的更改。
Cron守护程序每分钟都唤醒,并检查其配置以查看是否需要启动任何内容。
我们可以如下检查其状态

# systemctl status crond
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2016-08-19 03:12:38 UTC; 1 weeks 0 days ago
 Main PID: 3240 (crond)
   CGroup: /system.slice/crond.service
           └─3240 /usr/sbin/crond -n

a)crontab文件的语法

Crond如果定期执行Cron作业,如果它们符合/etc/crontab文件中定义的格式则执行。
用户的分类位于/var/spool/cron目录中。
存储系统分度的另一个位置是/etc/cron.d目录。
只允许root用户创建,修改或者删除它们。
Crond守护程序扫描两个位置的文件中的条目以确定作业执行计划。
而不是修改/etc/crontab,而不是在/etc/cron.d或者脚本中使用的cron文件,而不是在/etc/cron.hourly/etc/cron.daily/etc/cron.weekly,和/etc/cron.monthly

CRON表包括由空格或者标签字符分隔的六个字段。
前五个字段指定要运行命令的时间,第六字段是要执行命令的绝对路径名。
我们可以在shell脚本中放置命令,并在第六字段是shell脚本中的绝对路径名,调度它以重复运行。
Cron表的初始部分指定在执行命令时使用的环境。
该文件的其余部分包含注释,用于标识Cron表条目的格式。

# cat /etc/crontab 
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

按顺序列为:

  • 一小时(0-59):
  • 24小时时间昼夜时间(0-23):当天的时间在军用时间内列出。例如,为了表明工作是在下午3:00运行,我们将为该字段列出15
  • 日月(1-31)
  • 一年中的月份(1-12):如果我们更喜欢,我们可以使用名称的前三个字母而不是数字
  • 一周(0-7):0和7均对应周日。如果我们愿意,我们可以使用名称的前三个字母而不是数字
  • 执行命令或者脚本:在Cron作业的用户名之后,我们可以使用必须执行的脚本而不是命令

在Debian Systems上,CRONTAB文件的内容如下所示

cat /etc/crontab 
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user	command
17 *	* * *	root    cd/&& run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd/&& run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd/&& run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd/&& run-parts --report /etc/cron.monthly )

在前五个字段之后,"/etc/crontab"条目继续使用在第六字段中执行程序时使用的帐户名称。
例如,"/etc/crontab"中的任务定义"可以如下所示:

# This task would start 10 minutes after 5 a.m. on December 3 only.
10 5 3 12 * nobody /usr/bin/false
# run a task every minute between 5:00 a.m. and 5:59 a.m
* 5 * * * nobody /usr/bin/false

此文件中单个条目的解剖结构如下所述显示

  • 如果要匹配列(任何值)的所有值,请使用星号(*)
  • 由逗号分隔的列表,例如0,10,16匹配任何指定的值
  • 用短划线( - )分隔的两个值表示范围,包括终点
  • 与其他一些多值选项结合使用时,斜杠指定阶梯式值。阶梯式值是跳过一些成员的范围。例如,分钟字段中的*/30表示每30分钟运行的作业
# execute the /root/process.sh shell script at 5:20 PM and 5:40 PM Monday to Friday regardless of the day of the month or month of the year
20,40 17 * * 1-5 root /root/script.sh

b)创建或者编辑用户Cron表

通常,允许所有用户在Linux系统上安排作业,但只有root授权编辑/etc/crontab文件。
要创建用户Cron作业,请使用CRONTAB实用程序,不与"/etc/crontab"配置文件混淆。
CRONTAB的语法如下:

crontab [-u user] [-l | -e | -r] [file]

详细说明,我们有

  • -u:指定要使用的CRONTAB(列表时)或者修改(编辑时)的用户的名称
  • -L:它显示当前用户CRONTAB文件。
  • -r:删除当前用户crontab文件。所有Cron工作都将被删除
  • -e:它有助于编辑当前用户crontab文件。

安排每分钟执行的cron

每个用户都有自己的crontab文件,可以将-e选项用于crontab命令,该命令打开Vi编辑器,或者根据系统,将提出列表文本编辑器。

然后,我们可以输入相应的Cron表项:

$crontab -e
  # display the date into a file every minute
  * * * * * echo "it is $(date)" >> date-file

现在,我们可以在创建用户"Paul"的CRONTAB文件是否已创建

$cat /var/spool/cron/paul
  # display the date into a file every minute 
  * * * * * echo "it is $(date)" >> date-file

当我们不包含文件的完整路径时,它意味着该文件将在用户的主目录中创建。
现在我们可以看看我们的Cron工作

$cat /home/paul/date-file 
it is Thu Aug 31 03:43:01 UTC 2016
it is Thu Aug 31 03:44:01 UTC 2016
it is Thu Aug 31 03:45:01 UTC 2016
it is Thu Aug 31 03:46:01 UTC 2016

如果我们没有将输出重定向到文件中,它将每分钟电子邮件发送给用户

安排每五个(05)分钟执行的Cron

作为root用户,我们也可以使用-u参数编辑或者列出另一个用户的CRONTAB

# crontab -e -u stephen
  # ping the gateway every 05 minutes and redirect the result in a file 
  */5 * * * * ping -c 10 192.168.10.1 >> ping-file
# cat /home/stephen/ping-file 
PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data.
64 bytes from 192.168.10.1: icmp_seq=1 ttl=255 time=2.07 ms
64 bytes from 192.168.10.1: icmp_seq=2 ttl=255 time=2.63 ms
64 bytes from 192.168.10.1: icmp_seq=3 ttl=255 time=1.35 ms
64 bytes from 192.168.10.1: icmp_seq=4 ttl=255 time=1.04 ms

要删除用户的所有Cron作业,请使用以下命令

# crontab -r -u paul

我们可以查看如下结果

# crontab -l -u paul
no crontab for paul

在一周中的选定日期,在某个时间内安排Cron执行脚本

我们可以安排脚本而不是命令

# crontab -e -u paul
  #run a script to check the server cpu during the time where the charge can be max
  1-45 22-23 * * 0,1,4,6 /home/paul/check-cpu-script.sh >> check-cpu-file

我们可以检查结果

# cat /home/paul/check-cpu-file 
CPU utilization percentage : 1%|avg=1%;40;70;0;100 cpu0=1%

在一周的选定日期期间在特定时间内安排单个Cron中的多个任务

# crontab -e
11-45 18-20 * * 0,4,6 /home/paul/check-cpu-script.sh >> check-cpu-file; ping -c 10 192.168.10.1 >> check-cpu-file

我们可以如下检查文件

# cat /home/paul/check-cpu-file
CPU utilization percentage : 1%|avg=1%;40;70;0;100 cpu0=1%
PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data.
64 bytes from 192.168.10.1: icmp_seq=1 ttl=255 time=2.07 ms
64 bytes from 192.168.10.1: icmp_seq=2 ttl=255 time=2.63 ms

使用特殊语法的时间表任务

许多管理任务是每小时,每日,每周或者不计算的。
它们是指定的等效数字计划的基本捷径:

  • @每小时0 * * * *`每小时运行一次。
  • @ Daily0 0 * * *每天在午夜运行一次
  • @每周0 0 * * 0`在午夜周日每周运行一次。
  • @每月0 0 1 * *在本月的第一个月午夜运行。所以安排每个月开始的Cron工作
  • @每年1月1 1 *每年1月1日午夜运行一次。所以,如果我们希望在每年的第一分钟执行工作,我们可以使用它
  • "@重新启动"以重新启动后运行一次

所以你可以安排如下备份

# the cron 0 0 * * * /usr/local/bin/backup.sh can be define as below
@daily /usr/local/bin/backup.sh

如果我们有此类型的任务,则无需创建系统Cron表。
相反,我们可以在以下目录之一中放置运行相应命令的shell脚本:

  • 应在/etc/cron.hourly /目录中每小时执行的脚本
  • 应该在/etc/cron.daily /目录中执行的脚本
  • 应在/etc/cron.weekly /目录中每周执行的脚本
  • 应在/etc/cron.monthly /目录中每月执行的脚本

这些脚本的内容是Bash Shell脚本代码,它们不包含特定于Cron的任何时间指示符。
例如,要在每小时执行下面的脚本,我们必须在/etc/cron.hourly /目录中移动它

#vim /etc/cron.hourly/check-cpu.sh
  #!/bin/bash
  echo "it is $(date)" >> script-file-result
  /usr/lib/nagios/plugins/check_centreon_snmp_cpu -H localhost -C public -v 2c -w 40 -c 70 >> >> script-file-result

在Ubuntu系统上,"/etc/crontab"文件中的Cron表条目用于执行/etc/cron.hourly //etc/cron.daily //etc/cron的内容。 每周/,以及/etc/cron.monthly /目录。

一些cron调度解释

我会给你一些Cron工作安排解释,可以如下

  • 0 * 4 12 *命令:12月4日的每小时
  • 50 * * * *命令:每小时50分钟。所以±00 H 50,4小时50,14小时50等
  • 0 0 * * 1命令:午夜的每一个星期一(星期天到星期一的夜晚)。
  • 45 7 1-10 * *命令:每天早上7点到每月的一到10日。
  • 0 */2 * * *命令:每2小时(00 H 00,02 H 00,04 H 00 ......)
  • 0 4 * 12 *命令:12月4日的每天每天
  • */10 * * * 1-5命令:从周一到星期五的每10分钟
  • 0 0 * * 1,3,4命令:星期一,星期三和星期四的午夜

Cron很棒,但它有一个弱点:它专为持续运行的机器而设计。
如果当作业落下时,机器已关闭,则不会运行它。
它存在另一个解决方案,有助于在服务器后启动时执行任务。

2)使用anacron服务计划任务

anacron是一种简化的Cron,它补充了现有的Cron系统。
它是为了处理每天或者更少运行的作业,频繁地运行精确时间并不重要。
Anacron在Cron的主要优势是它运行了在计算机关闭时计划去的工作。

开发了anacron,以确保将以保证的时间间隔执行特定任务。
这可确保如果系统暂时关闭维护,则该任务也会运行。

a)anacron文件的语法

为了确保定期执行作业,Cron使用anacron服务。
无论在哪个确切的时间,这项服务都会照顾每小时,每日,每周和每月Cron工作。
要确定应如何完成,Anacron使用"/etc/anacrontab"文件"。

/etc/anacrontab中,要执行的作业是以包含四个字段的行指定

# 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的语法可以被认为如下所述:

  • 期间(在天中):第一个字段指定作业执行的频率,在几天内表示。例如,此字段中的1(一个)意味着每天运行它。我们可以使用特殊语法"@"
  • 延迟(在分钟内):第二列指定在执行作业之前的anacron等待长度。延迟功能旨在帮助系统在启动时需要运行多个命令时,保持系统重载(overloading)。
  • 作业标识符:它标识命令。其目的是识别消息,日志文件和特殊执行中的作业
  • 命令:最后一个字段是应该执行的命令

漂亮命令以较低的优先级运行命令。
运行部件是一个工具,附带的Cron,它一个接一个地在给定目录中运行每个文件。

b)与anacron的时间表任务

正如我们所看到已经有内容的anacron文件的语法一样,我们可以在文件末尾插入作业

@daily    15    rsync.daily   /bin/bash /home/steven/script/backuprsync.sh

如果系统下降,Anacron将在系统备份后15分钟执行脚本。

虽然有用的是知道anacron如何工作,但它通常不是通常建议直接配置的服务。
通过anacron配置服务的需要被cron.hourly,cron.daily,cron.weekly和cron.monthly文件带走。
当然,要做任何好处,必须称为anacron效用。
要在Anacron中安排作业,我们可以将脚本放入右侧文件夹中并为方便起见而更改延迟。

测试anacron语法

可以使用下面的命令检查Anacrontab文件的任何语法错误或者其他问题

# anacron -T

如果存在任何错误,则我们将具有以下消息,如下所述,指示错误的行

anacron: /etc/anacrontab: Unknown named period on line 17, skipping

在前景中运行anacron工作

通常anacron叉背景作业,它只在屏幕上显示任何内容。
但有时我们需要在屏幕上看到输出。
可以使用以下命令的d参数:

# anacron -d
Anacron started on 2016-09-01

强制anacron工作执行

要强制执行anacron作业,可以使用-f选项。
此选项具有仍然考虑anacrontab文件中指定的延迟的特殊性。

# anacron -d -f
Anacron started on 2016-09-01
Will run job `cron.daily' in 34 min.
Will run job `rsync.daily' in 44 min.
Will run job `cron.weekly' in 54 min.
Will run job `cron.monthly' in 74 min.

立即强制anacron工作执行

尽管通过尊重延迟来迫使执行的-f选项,但"-N"参数"迫使我们启动它的当前即时的执行。
它不会考虑任何延误。

# anacron -d -n
Anacron started on 2016-09-01
Checking against 0 with 31
Will run job `rsync.daily'
Jobs will be executed sequentially
Job `rsync.daily' started
Job `rsync.daily' terminated (exit status: 3) (mailing output)
Normal exit (1 job run)

其他Cron文件夹中没有其他脚本/作业

3)与服务安排工作

有时cron和anacron是矫枉过正的。
而Cron用于安排需要定期执行的作业,则ATD服务可用于仅需要执行一次的服务。
要通过ATD服务运行作业,我们将使用AT命令。
AT命令的任务或者作业在/var/spool/at目录中排队,其中一个文件表示每个作业。

a)在命令语法中

在普通使用中,AT命令只需要一个选项:运行的时间可以是

  • 特定时间(一天中的时间):我们可以将一天的时间指定为hh:mm,可选择后跟AM或者PM如果使用12小时格式。如果指定的时间已通过,则计划在下一次发生的情况下计划
  • 一个时间指示:它存在关键字,它代表我们所期望的中午(12:00),午夜(00:00),或者下午时间(16:00)
  • 指定的一天:要提前24小时以上时间安排在工作时间上,必须在日期规范后添加日期规范。这可以使用MMDDYY,MM/DD/YY或者DD.MM.YY格式以数字形式完成。或者,我们可以根据月份名称或者月份日年份指定日期。
  • 将来指定的时间段:我们可以使用关键字,plus符号+`以及在指定时间运行作业的时间段来指定时间。

b)创建,编辑,列出或者删除"AT"作业

使用AT命令使用上面的一个表单之一后,将打开AT AT Shell。
从此shell中,我们可以键入将在提到的特定时间执行的几个命令。
进入命令后,使用ctrl-d退出AT Shell。

在指定时间安排任务

# at 2pm 
at> echo "Good afternoon" 
at> <EOT>

我们应该收到邮件的邮件。

安排未来的任务

# at 04:47 09/08/17
at> tail -f -n 30 /var/log/centreon-engine/centengine.log >> /home/paul/centengine-log
at> <EOT>

我们可以在以下几周内安排任务

# at now +2 weeks

列表和删除计划任务

在使用AT调度作业后,我们可以使用ATQ命令(Q. Queue)来获取当前计划的所有作业的概述。
还可以使用ATRM命令删除作业时的电流

# atq
1	Fri Sep  1 06:19:00 2016 a root
2	Fri Sep  1 06:20:00 2016 a root
4	Fri Sep  1 05:30:00 2016 a root
3	Fri Sep  1 05:20:00 2016 a root
5	Fri Sep  1 14:00:00 2016 a root
10      Fri Sep  8 04:47:00 2016 a root

我们可以看到在指定时间执行的任务。
我们可以删除以下任务

# atrm 10

我们可以通过再次列出计划任务来查看

# atq
1	Fri Sep  1 06:19:00 2016 a root
2	Fri Sep  1 06:20:00 2016 a root
4	Fri Sep  1 05:30:00 2016 a root
3	Fri Sep  1 05:20:00 2016 a root
5	Fri Sep  1 14:00:00 2016 a root

4)允许和不允许用户进行预定作业

默认情况下,所有用户都可以安排作业,并且可以使用某些特殊或者许可文件来限制允许哪些用户安排作业

a)管理"cron"安全

可以使用使用/etc/cron.allow/etc/cron.deny配置文件来限制允许哪个用户安排Cron作业。
如果存在cron.allow文件,则必须其中列出用户以允许使用Cron。
如果存在crondeny文件,则不得其中列出用户以允许设置Cron作业。
如果任何文件都不存在,只有root只能管理cron作业

b)管理"在"安全

AT有一组安全文件,/etc/at allow/etc/at.deny,它允许用户或者阻止用户在作业上排队。
如果AT.Allow文件存在并包含用户名,只允许允许root用户使用。
如果存在的/etc/at.deny文件存在并包含用户名,则拒绝这些用户,允许所有其他用户。
如果任何文件都不存在,只允许root用户在作业上提交。

5)关于路径和全球环境的问题

在命令行运行时,脚本可以正常工作,但在从Cron运行时不起作用,这是一个常见的问题。
环境不同,因为Cron没有运行.bash_profile.bashrc脚本。
因此,我们可以期望最少的环境,包括基本路径。
我们还可以指示shell环境,然后遵循Cron作业

# crontab -e
PATH=/your_script_path:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
15 1 * * 3-7 script.sh >> script-result