特定时间运行脚本
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作业的例子。我们将stdout和stderr重新路由到/dev/null*以在执行期间抑制命令输出*:
要在每天 23:00(晚上 11 点)运行backup.sh并将stdout和stderr输出到*/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文件来限制访问at和batch*服务的用户。
现在,让我们通过简单地将用户名添加到*/etc/at.deny文件来阻止用户jack访问at和batch*服务:
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.