Contents

特定时间运行脚本

1. 概述

通常情况下,作为系统管理员,我们必须定期运行脚本以保持我们的系统基础设施清洁和安全。

这些重复性任务包括系统备份、健康监控和其他维护工作。在这种情况下,自动化是达到目的的最好和最快的方法。 本教程将详细介绍在 Linux 系统中在特定时间安排作业的不同方法。

2. 计划

cron 是用于安排任务的通用软件服务。它包含两个关键组件:cron 守护进程 ( crond ) 和 cron 配置。crond读取 cron 配置以确定何时运行哪个任务。它遍历/var/spool/cron/etc/crontab和*/etc/cron.d*下的所有文件以执行命令。

现在,让我们深入了解它的本质。

2.1. crontab

*crontab *是管理所有 cron 作业的命令行实用程序。cron 包在所有最新的 Linux 变体系统中默认可用。如果没有,我们可以使用包管理器安装它:

$ dpkg -l cron
dpkg-query: no packages found matching cron
$ sudo apt-get update && sudo apt-get upgrade -y
$ sudo apt-get install cron -y
...
...
$ dpkg -l cron
...
...
||/ Name                                 Version                 Architecture            Description
+++-====================================-=======================-=======================-=============================================================================
ii  cron                                 3.0pl1-128.1ubuntu1     amd64                   process scheduling daemon
$ systemctl status cron
● cron.service - Regular background program processing daemon
   Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2021-08-14 20:51:25 IST; 1 weeks 2 days ago
...
...

crontab -l命令将列出所有 cron 作业。我们可以使用*#*符号添加注释:

$ crontab -l
# Edit this file to introduce tasks to be run by cron.
...
...
#
0 5 * * 1 tar -zcf /var/backups/home.tgz /home/

由于vi编辑器通常是编辑 cron 配置的首选工具,让我们通过export命令将默认编辑器更改vi ,并使用crontab -e编辑 cron 表:

$ export EDITOR=vi
$ crontab -e
# Edit this file to introduce tasks to be run by cron.
0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
...
...
# [minute] [hours] [day of month] [month] [day of the week] command-to-execute

这些字段中的每一个都有一个允许的整数值范围:

  • 分钟– 0 到 59
  • 小时– 0 到 23
  • 一个月中的第几天- 1 到 31
  • – 1 到 12
  • 星期几– 0 到 7,其中 0 或 7 表示星期日,1 是星期一,2 是星期二,依此类推,6 表示星期六

让我们看几个cron作业的例子。我们将stdoutstderr重新路由到/dev/null*以在执行期间抑制命令输出*:

要在每天 23:00(晚上 11 点)运行backup.sh并将stdoutstderr输出到*/dev/null*文件:

00 23 * * * /home/blogdemo/backup.sh > /dev/null 2>&1

系统范围的cron环境变量可以在*/etc/crontab*中设置:

$ cat /etc/crontab
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
...

此外,系统管理员拥有通过*/etc/cron.allow/etc/cron.deny文件限制cron*访问的所有权限。

2.2. cron特殊字符

cron表达式通常包含一个或多个帮助我们安排任务的特殊字符。 星号 (*) 匹配给定字段的所有可能值。让我们看看它的实际效果:

00 15 * * * /home/blogdemo/backups.sh

在这里,通过在最后三个字段(1-31 天、1-12 个月、一周中的所有天数)中使用星号,我们的backups.sh脚本将在每天下午 3 点运行。

斜杠**(/) 表示给定范围的增量**:

02-50/10 * * * * /home/blogdemo/monitor-cpu.sh

在上面的表达式中,分钟字段中的 2-50/10 表示该小时的第二分钟,此后每 10 分钟。因此,脚本将在每小时的第 2、12、22、32 和 42 分钟运行。

字符 (-) 表示连续范围,而逗号 (,) 分隔值列表

(@) 处的符号**允许使用内置的 cron 调度程序,例如@reboot@hourly@daily@monthly和*@yearly*。例如,我们可以安排一个脚本在每次重启后执行:

@reboot (cd /home/blogdemo/monitoring-scripts; bash monitor-memory.sh)

此处,分号 (;) 将命令附加到执行列表。在此示例中,首先,它转到*/home/blogdemo/monitoring-scripts路径,然后执行脚本monitor-memory.sh*。

我们关于cron 表达式的 文章进一步阐明了 cron 使用的所有可能选项。 此外,我们还可以将脚本放在*/etc/cron.hourly*、/etc/cron.daily/etc/cron.weekly/etc/cron.monthly和*/etc/cron.yearly*目录中,分别执行:

$ ls -ltr /etc/cron.daily/
total 48
-rwxr-xr-x 1 root root  372 Aug 21  2017 logrotate
-rwxr-xr-x 1 root root 1176 Nov  3  2017 dpkg
-rwxr-xr-x 1 root root  249 Jan 25  2018 passed
...

驻留在cron.daily目录中的上述脚本每天都会执行。

通常,我们应该避免**为root用户运行cron任务调度程序。**同样,不建议直接在cron命令上使用复杂的代码、管道或重定向。相反,我们应该将复杂的作业定义为脚本并从cron调用脚本。

3. at

*at *是另一个调度程序服务,它允许我们在特定时间执行命令,但只能执行一次

at包在所有最新的Linux 变体系统中默认可用。如果没有,我们可以使用包管理器安装它:

$ which at
$
$ sudo apt install at -y
...
...
$ which at
/usr/bin/at

通过给定时间参数,我们可以很容易地通过命令行安排任务。 现在让我们看看:

$ date
Wed Aug 25 06:49:57 IST 2021
$ date > current-time.txt | at now
warning: commands will be executed using /bin/sh
job 9 at Wed Aug 25 06:50:21 2021
$ cat current-time.txt
Wed Aug 25 06:50:22 IST 2021

内联命令执行通过利用at命令的*-f*选项帮助我们运行脚本:

$ at 09:00 -f /home/blogdemo/one-time-env-setup.sh

或者,我们可以at终端中安排作业。为了便于说明,让我们创建一个在 06:42 运行的新作业,以将日期和时间写入at-demo.txt文件:

$ at 06:42
warning: commands will be executed using /bin/sh
at> date > at-demo.txt
at> 
job 2 at Sat Aug 14 06:42:00 2021
$ ls -ltrh
total 4.0K
-rw-rw-r-- 1 tools tools 29 Aug 14 06:42 at-demo.txt
$ cat at-demo.txt
Sat Aug 14 06:42:00 IST 2021

我们可以使用atq命令列出at队列中的用户计划作业。

让我们从输出的左侧读取作业 ID、日期时间、队列字母和用户。队列字母可以从 a 到 z 和 A 到 Z,其中较低值的字母具有较低的 nice 值,较高值的字母具有较高的 nice 值:

$ atq
2       Sat Aug 14 06:42:00 2021 a tools

atrm命令从任务调度程序列表中删除作业:

$ atq
14      Fri Aug 27 06:42:00 2021 a tools
$ atrm 2
$ atq
$

4. batch

有趣的是,batch 命令是at命令的扩展功能。它根据 CPU 负载而不是时间参数执行命令。

当系统的平均 CPU 负载小于 1.5 时,系统将执行调度命令

调用batch命令的另一种方法是在* -b *处。

首先,让我们看一个 CPU 负载小于 1.5 的batch命令示例。

通常,*top *命令有助于识别当前的 CPU 负载:

top - 17:20:50 up 11 days, 20:29,  2 users,  load average: 0.00, 0.00, 0.00
Tasks: 405 total,   1 running, 306 sleeping,   0 stopped,   0 zombie
$ batch
warning: commands will be executed using /bin/sh
at> date > batch-test.txt
at> 
job 17 at Thu Aug 26 17:21:00 2021
$ ls -ltrh
-rw-rw-r-- 1 tools tools    29 Aug 26 17:22 batch-test.txt
$ cat batch-test.txt
Thu Aug 26 17:22:12 IST 2021

在这种情况下,batch没有执行计划的命令,因为 CPU 负载超过 1.5

top - 17:24:28 up 11 days, 20:37,  2 users,  load average: 6.91, 3.47, 1.38
Tasks: 413 total,   8 running, 306 sleeping,   0 stopped,   0 zombie
$ date
Thu Aug 26 17:26:45 IST 2021
$ batch
warning: commands will be executed using /bin/sh
at> date > batch-load-test.txt
at> 
job 19 at Thu Aug 26 17:26:00 2021
$ date
Thu Aug 26 17:28:49 IST 2021
$ ls -ltrh batch-load-test.txt
ls: cannot access 'batch-load-test.txt': No such file or directory
$ atq
19      Thu Aug 26 17:26:00 2021 b tools

我们可以使用*/etc/at.deny/etc/at.allow文件来限制访问atbatch*服务的用户。

现在,让我们通过简单地将用户名添加到*/etc/at.deny文件来阻止用户jack访问atbatch*服务:

root@sandbox1:~$ cat /etc/at.deny | grep jack
jack
root@sandbox1:~$ at
You do not have permission to use at.
root@sandbox1:~$ batch
You do not have permission to use at.