Products
GG网络技术分享 2025-03-18 16:14 0
在计算机上让任务按照有规律并且可预测的时间表运行很重要。作为人类,我们有时会因为分心、脑子里想太多,或是度假而记不住要做的事情。计算机真的很擅长按计划做事,但在计算机采取行动之前,人类必须对计算机进行编程。
在某种程度上,cron 系统是编程的初级简单入门。通过编辑一个文件就可以让计算机做你想让它做的事。你甚至不需要知道文件保存在哪里。只需键入一个简单的命令,输入你希望电脑遵循的 “配方”,并保存。从那时起,计算机会在指定时间执行你的指令,直到被告知停止。
从设计上来看,cron 不是一个复杂的系统。这里有一些你需要了解的内容。
cron 命令在 Linux 和 Unix 中无处不在,而且它经常被模仿和重塑,以至于它几乎成了按计划发生的事情的一个通用术语。它是自动化的一种形式,尽管有不同的实现方式(比如 Dillon\'s cron、Vixie\'s cron、chrony 和其他),以及像 anacron 和 systemd 定时器这样的变化,但其语法和工作流程几十年来一直保持着基本一致。
cron 在一个 “假脱机spool” 系统上工作,像打印机和电子邮件一样。如果不你知道打印机和电子邮件使用假脱机也没关系,因为假脱机文件的意义在于,你不需要想太多。在 Linux 系统中,/var/spool
目录被设计为重要但低级的文件的中心枢纽,用户不需要直接与之交互。 在/var/spool
中管理的一个假脱机是 cron 表(简称为 “crontab”)。 包括你在内的每个用户在 Linux 系统中都有一个 crontab。用户可以编辑、查看和删除自己的 crontab。除此之外,用户可以使用 crontab 来安排任务。cron 系统监控 crontab,并确保一个 crontab 中列出的任何工作都能在其指定时间执行。
你可以使用 crontab
命令和-e
(代表“编辑”)选项来编辑你的 crontab。默认情况下,大多数系统会调用vim
文本编辑器。如果你和我一样,不使用 Vim,那么你可以在~/.bashrc
文件中为自己设置一个不同的编辑器。我把我的设置为 Emacs,但你也可以试试Nano、Kate,或者任何你喜欢的编辑器。EDITOR
环境变量定义了你在终端使用的文本编辑器,而VISUAL
变量定义了你在图形模式下使用的编辑器:
export EDITOR=nano
export VISUAL=kate
更新设置后刷新你的 shell 会话:
$ source ~/.bashrc
现在你可以用喜欢的编辑器编辑 crontab:
$ crontab -e
cron 系统本质上是一个日历系统。可以通过五个不同的属性告诉 cron 需要让一个任务多长时间运行一次:分、时、日、月、星期。这些属性的顺序是固定的,并且不一定是直观的,你可以把它们看作是过滤器或掩码。默认情况下,你可以理解为所有东西都被设置为“总是”或者“每一个”。此命令将在全年的每一天每小时每分钟运行 touch /tmp/hello
:
* * * * * touch /tmp/hello
可以通过设置每个属性的具体定义来限制这个包罗万象的时间安排表。使任务在每个小时的 30 分钟时运行,将分钟设置为 30
:
30 * * * * touch /tmp/hello
可以通过一个具体的小时来进一步约束这个指令。使任务在每个凌晨 3:30 运行:
30 3 * * * touch /tmp/hello
你也可以让这个任务只在每个月的第一天运行:
30 3 1 * * touch /tmp/hello
你可以用 1
至12
表示 1 至 12 月来设置月份,用0
至6
表示周日至周六来设置星期。这项任务在 4 月份的周一的 3:15 运行:
15 3 * 4 1 touch /tmp/hello
所有这些设置都与一个固定时间 完全匹配。使用 cron 符号设置可以在特定时间段后运行任务,例如,每 15 分钟运行一个任务:
*/15 * * * * touch /tmp/hello
每三天在上午 10 点运行任务:
* 10 */3 * * touch /tmp/hello
每 6 小时运行一次任务:
* */6 * * * touch /tmp/hello
现代的 cron 实现已经为常见的时间安排表添加了方便的速记符,包括:
@hourly
:每小时@daily
:每天@weekly
:每周@monthly
:每月@yearly
或@annually
:每年使用 crontab
命令,查看计划中的 cron 任务列表:
$ crontab -l
15 3 * 4 1 touch /tmp/hello
当一个 crontab 任务不需要时,可以使用 -r
选项来删除它:
$ crontab -r -i
-i
选项代表交互式。它在删除文件之前会提示你进行确认。
知道如何使用 cron 是一回事,但但知道它的用途是另一回事。经典用例就是备份计划。如果你的电脑一天中大部分时间都是开着的,或者整天整夜地开着,那么可以为重要分区进行例行备份。我会在每天凌晨 3 点在主要数据分区上运行一个名为 rdiff-backup
的备份程序:
$ crontab -l | grep rdiff
* 3 * * * rdiff-backup /data/ /vault/
另一个常见的用途是系统维护。在我的 Slackware 桌面上,每周五下午会更新本地版本库目录:
$ crontab -l | grep slack
* 14 * * 5 sudo slackpkg update
我还会每 3 天在 15:00 运行一个 Ansible 脚本来 清理我的下载文件夹:
$ crontab -l | grep ansible
* 15 */3 * * ansible-playbook /home/seth/Ansible/cleanup.yaml
有一些重复数据删除脚本、文件大小和 /tmp
目录的监视器、照片调整器、文件移动工具以及很多琐碎的任务,你可以安排在后台运行,以帮助保持系统不受干扰。有了 cron,计算机可以以我希望我的实体公寓能够做到的方式来照顾自己。
除了想明白你为什么需要 cron 之外,根据我的经验,cron 最难的事情是记住它的语法。重复这句话给自己听,反反复复,直到你记牢它:
更好的做法是,去 下载我们免费的速查表,这样当你最需要它时,它触手可及!
via: https://opensource.com/article/21/11/cron-linux
作者:Seth Kenlon选题:lujun9972译者:Veryzzj校对:wxy
本文由 LCTT原创编译,Linux中国荣誉推出
Crontab是linux下定时调度配置文件,通过它,我们可以让系统的程序、脚本、命令、任务按设定的时间、间隔、周期循环的运行。 在Crontab里时间粒度最小的是分钟。也就是说,通过Crontab配置,我们最多可以让目标任务每分钟执行一次,更频繁的执行是不行的,只能借助其它方法。
比如说,如果希望一个程序每30秒执行一次,该怎么办呢?
变通的方法还是有的。 一种思路是,在Crontab里添加两条配置,一条是正常调度,每分钟执行一次,另一条是等待30秒后才执行。
# Need these to run on 30-sec boundaries, keep commands in sync. * * * * * /path/to/executable param1 param2 * * * * * ( sleep 30 ; /path/to/executable param1 param2 ) |
这种方法感觉有点生硬,怪怪的,但的确可行。这种方法实际是可以简写成一行:
* * * * * /bin/bash -l -c \"/path/to/executable; sleep 30 ; /path/to/executable\" |
还有一种方法是使用watch命令:
$ watch --interval .30 script_to_run_every_30_sec.sh |
但watch是命令行工具,我们可以使用nohup命令让它在后台运行。
SystemD定时器
如果我们使用的linux系统里有SystemD,可以使用SystemD定时器在任何时间粒度上调度程序,理论上可以小到纳秒级别——当然,这样做有点疯狂。总之,它在任务调度上的灵活性远比Cron要高——无需使用sleep这种蹩脚的方案。
比起一行完成配置的crontab来说,建立一个SystemD定时器会显得稍微复杂一些,但为了更好的实现小于‘每分钟’粒度的调度任务,这种方法值得尝试。
SystemD定时器实现原理简单说就是两部分:一个系统service,一个SystemD定时器。SystemD定时器执行调度,而任务是写在service里。
下面有个简单的例子,目标是让系统logger每十秒钟输出一次“Hello World”;
/etc/systemd/system/helloworld.service
[Unit] Description=Say Hello [Service] ExecStart=/usr/bin/logger -i Hello World |
/etc/systemd/system/helloworld.timer
[Unit] Description=Say Hello every 10 seconds [Timer] OnBootSec=10 OnUnitActiveSec=10 AccuracySec=1ms [Install] WantedBy=timers.targethelloworld.timer里并没有声明service的名称,那它和service是如何关联的呢?没错,因为它们的名称相同,都是helloworld。 |
如果想让整个系统使用这个定时器,这两个文件就需要放置在/etc/systemd/system下。如果想给某个用户使用,则放置在~/.config/systemd/user。想让这个定时器立即运行,需要执行下面的命令:
systemctl enable --now helloworld.timer |
里面的–now标记是让定时器立即执行。否则,只有等系统重启后,或者用户登录是才会触发运行。
[Timer]部分里的各个字段的作用如下:
OnBootSec– 系统启动多少秒后开始执行调度
OnUnitActiveSec– 重复调度相关service的时间间隔。就是这行配置决定了跟cron job一样定时调度的动作。
AccuracySec– 定时器精度。 默认是一分钟,跟cron很相似。可以要求的更高,但精度增加会带来更多系统的消耗,更频繁的唤醒CPU。上面的配置里写的是1ms,显然不是个聪明的决定。通常我们可以把它设置为1(1秒),对于我们这样低于1分钟时间粒度的定时器的精度要求已经够用了。也是因为如此,我们会看到,实际程序运行时输出“Hello World”消息的时间经常会延迟1秒左右。如果你认为这一秒左右的延迟不是问题,那就应该这样设定。
你会发现,SystemD定时器和Crontab定时器并不是一样的——任务调度的周期并不是按年月日小时分钟周期设定的,它是按我们第一次执行它的时间开始,每次追加一个周期的时间。如果我们钟情于Crontab那样的时间配置方式,SystemD定时器也是支持的,那就需要把OnBootSec和OnUnitActiveSec去掉,换成OnCalendar,下面是一个例子:
OnCalendar=*-*-* *:*:00,10,20,30,40,50 |
最后补充一点,默认情况下,SystemD定时器和service的关联是通过相同的名称,如果你愿意,也可以在[Timer]配置里通过指定Unit字段配对。
上面的几种方法都可以实现低于分钟粒度的定时调度任务。各有优点。SystemD定时器看起来更正规,但稍微复杂了一点。Crontab+sleep方式虽然别扭,但对于一些小任务来说没有不能胜任的。
以上就是让Crontab每秒钟执行一次任务的方法的详细内容,更多请关注网站的其它相关文章!
Demand feedback