通过使用这个简单而强大的 Linux 命令行工具，来安排备份、文件清理以及其他任务。在计算机上让任务按照有规律并且可预测的时间表运行很重要。作为人类，我们有时会因为分心、脑子里想太多，或是度假而记不住要做的事情。计算机真的很擅长按计划做事，但在计算机采取行动之前，人类必须对计算机进行编程。在某种程度上，cron 系统是编程的初级简单入门。通过编辑一个文件就可以让计算机做你想让它做的事。你甚至不需要知道文件保存在哪里。只需键入一个简单的命令，输入你希望电脑遵循的 “配方”，并保存。从那时起，计算机会在指定时间执行你的指令，直到被告知停止。从设计上来看，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 中列出的任何工作都能在其指定时间执行。编辑 cron 设置你可以使用 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 速记符现代的 cron 实现已经为常见的时间安排表添加了方便的速记符，包括：@hourly：每小时@daily：每天@weekly：每周@monthly：每月@yearly 或 @annually：每年列出 cron 任务使用 crontab 命令，查看计划中的 cron 任务列表：$ crontab -l 15 3 * 4 1 touch /tmp/hello 删除一个 crontab当一个 crontab 任务不需要时，可以使用 -r 选项来删除它：$ crontab -r -i -i 选项代表 交互式。它在删除文件之前会提示你进行确认。Cron 可以做什么知道如何使用 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 之外，根据我的经验，cron 最难的事情是记住它的语法。重复这句话给自己听，反反复复，直到你记牢它：分、时、日、月、星分、时、日、月、星分、时、日、月、星更好的做法是，去 下载我们免费的速查表 ，这样当你最需要它时，它触手可及！Cron 速查表via: https://opensource.com/article/21/11/cron-linux作者：Seth Kenlon 选题：lujun9972 译者：Veryzzj 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
在本期的《Linux 黑话解释》系列文章中，你将了解到 Linux 中的 定时任务 cron job 功能。你将通过学习编辑 crontab 文件来创建定时任务。何为定时任务cron 是一个用于按计划运行短小且快速的命令的实用命令行工具。该工具是一个方便、经典的系统管理工具，通过和其他工具结合使用可以自动运行各式各样的任务。比如，有些人通过把 rsync 和 cron 结合使用，在特定的时间自动创建每日备份和每周备份。也有些人使用 cron 来分析服务器日志，并且结合邮件系统功能，在日志检测到错误时自动发送告警邮件。cron 就如同“瑞士军刀”一样，可以多场景多样化使用。尽可能发挥你的想象，去挖掘它的功能。其实 cron 的使用很容易上手，只需要几秒钟。不过在我们开始上手之前，先来讨论下几个经常容易混淆的概念。cron、定时任务、crontab有三个术语比较容易混淆：cron、定时任务和 crontab，让我们来看看它们的含义：术语含义cron这是安装在系统上的实际执行定时任务的 守护进程。定时任务“任务”是指一段启动并运行的程序。cron 可以按照约定的时间计划运行各种任务，这样的任务通常叫做“定时任务”。crontab这是一个文件，用于定义定时任务。一个 crontab 文件可以通过表格形式（每一行就是一个定时任务）定义多个定时任务。来看一个简单例子：创建一个定时任务，每小时向 crontabl_log.txt 文件打印 Linux is cool!。0 * * * * echo "Linux is Cool!" >> ~/crontab_log.txt 是不是这么个简单定时任务的例子都让你感到惊恐，这是因为你需要懂得如何去读懂一个定时任务的属性。我将在后文中讲述这个基础理论知识。上手 cron我们通过另一个例子来看看 cron 如何工作。为了创建定时任务（或者说 cron 将要执行的命令任务），你只需要运行：crontab -e 这将会打开一个文件，用于编辑定时任务：其中，所有以 # 开头的行都是注释，用于指导你如何使用 cron，如果觉得没用可以删除它们。我们将创建如下任务，作为我们的第一个定时任务：* * * * * touch ~/crontab_test 让我快速看看该任务将会做什么：定时任务都是以 “分钟 小时 天 月 周 命令” 形式呈现：分钟：指该任务在哪一分钟会被执行。所以，该值为 0 则代表在每个小时开始时运行，5 则代表在每个小时的第 5 分钟会运行。小时：指该任务在一天中的哪个小时会被执行，取值范围为 0-23。没有 24 的原因是 23 时的末尾是半夜 11:59，然后就是每天的开始 0 时。分钟的取值范围定义逻辑与之类似。天：指一个月中的哪一天执行该任务，取值范围是 1-31（不同于前面的分钟和小时从 0 开始取值）。月：指该任务在哪个月被执行，取值范围是 1-12。周：指该任务在星期几被执行，从周日开始算起，取值范围是 0-6（分别对应周日、周一到周六）。命令：是你想要运行的命令任务。如果想对 “分钟 小时 天 月 周” 部分有更详细的理解，可以参考 Crontab guru 网站，该网站可以帮助你理解正在执行什么。接着之前的例子 * * * * * touch ~/crontab_test，表示每分钟创建一次 ~/crontab_test 文件。让我们将该任务编辑进 crontab 然后看看执行结果：等到下一分钟，你就会发现你的家目录下多了文件 crontab_test:这便是 cron 的基础应用示例。一个实用的定时任务示例假设你想创建一个脚本，用于拷贝多个目录内容到一个路径并打包作为备份，该如何实现？通过 cron 定时任务就可以很容易实现该功能。请看如下脚本：#!/usr/bin/bash echo "Backing up..." mkdir -p ~/.local/tmp/ tar -Pc ~/Documents/ -f ~/.local/tmp/backup.gz 该脚本做了如下事情：确保备份路径目录 ~/.local/tmp/ 存在。将目录 ~/Documents/ 下的所有内容打包至文件 ~/.local/tmp/backup.gz。我们先来手动运行该脚本，看看它到底如何工作。首先，我们在家目录（~）下创建该脚本，命令为 backup_script，如下图所示：然后编辑 backup_script 脚本，写入上面那个脚本代码。接着，赋予 backup_script 可执行权限：最后运行脚本 ~/backup_script，进行功能验证：你可以通过运行命令 tar -xf ~/.local/tmp/backup.gz -C <output_dir> 来进行备份恢复，这里 <output_dir> 是指文件要恢复到的路径目录。接下来，就可以用 cron 工具来进行定时任务运行该脚本了。举个例子，假设需要每天的凌晨 3 点运行该备份脚本，你可以在 crontab 中输入如下命令：* 3 * * * ~/backup_script 这样你就可以每天自动进行备份操作了。后记本文简单介绍了定时任务功能。尽管我不确定 Linux 桌面用户使用该功能多不多，但我知道定时任务功能被许多系统管理员广泛应用。如果你有什么想法，欢迎在评论区留言。via: https://itsfoss.com/cron-job/作者：Hunter Wittenborn 选题：lujun9972 译者：jrglinux 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
在 Linux 系统中有一些其他开源项目可以结合或者替代 cron 系统使用。Linux cron 系统 是一项经过时间检验的成熟技术，然而在任何情况下它都是最合适的系统自动化工具吗？答案是否定的。有一些开源项目就可以用来与 cron 结合或者直接代替 cron 使用。at 命令cron 适用于长期重复任务。如果你设置了一个工作任务，它会从现在开始定期运行，直到计算机报废为止。但有些情况下你可能只想设置一个一次性命令，以备不在计算机旁时该命令可以自动运行。这时你可以选择使用 at 命令。at 的语法比 cron 语法简单和灵活得多，并且兼具交互式和非交互式调度方法。（只要你想，你甚至可以使用 at 作业创建一个 at 作业。）$ echo "rsync -av /home/tux/ me@myserver:/home/tux/" | at 1:30 AM 该命令语法自然且易用，并且不需要用户清理旧作业，因为它们一旦运行后就完全被计算机遗忘了。阅读有关 at 命令 的更多信息并开始使用吧。systemd除了管理计算机上的进程外，systemd 还可以帮你调度这些进程。与传统的 cron 作业一样，systemd 计时器可以在指定的时间间隔触发事件，例如 shell 脚本和命令。时间间隔可以是每月特定日期的一天一次（例如在星期一的时候触发），或者在 09:00 到 17:00 的工作时间内每 15 分钟一次。此外 systemd 里的计时器还可以做一些 cron 作业不能做的事情。例如，计时器可以在一个事件 之后 触发脚本或程序来运行特定时长，这个事件可以是开机，可以是前置任务的完成，甚至可以是计时器本身调用的服务单元的完成！如果你的系统运行着 systemd 服务，那么你的机器就已经在技术层面上使用 systemd 计时器了。默认计时器会执行一些琐碎的任务，例如滚动日志文件、更新 mlocate 数据库、管理 DNF 数据库等。创建自己的计时器很容易，具体可以参阅 David Both 的文章 使用 systemd 计时器来代替 cron。anacron 命令cron 专门用于在特定时间运行命令，这适用于从不休眠或断电的服务器。然而对笔记本电脑和台式工作站而言，时常有意或无意地关机是很常见的。当计算机处于关机状态时，cron 不会运行，因此设定在这段时间内的一些重要工作（例如备份数据）也就会跳过执行。anacron 系统旨在确保作业定期运行，而不是按计划时间点运行。这就意味着你可以将计算机关机几天，再次启动时仍然靠 anacron 来运行基本任务。anacron 与 cron 协同工作，因此严格来说前者不是后者的替代品，而是一种调度任务的有效可选方案。许多系统管理员配置了一个 cron 作业来在深夜备份远程工作者计算机上的数据，结果却发现该作业在过去六个月中只运行过一次。anacron 确保重要的工作在 可执行的时候 发生，而不是必须在安排好的 特定时间点 发生。点击参阅关于 使用 anacron 获得更好的 crontab 效果 的更多内容。自动化计算机和技术旨在让人们的生活更美好，工作更轻松。Linux 为用户提供了许多有用的功能，以确保完成重要的操作系统任务。查看这些可用的功能，然后试着将这些功能用于你自己的工作任务吧。（LCTT 译注：作者本段有些语焉不详，读者可参阅譬如 Ansible 自动化工具安装、配置和快速入门指南 等关于 Linux 自动化的文章）via: https://opensource.com/article/21/7/alternatives-cron-linux作者：Seth Kenlon 选题：lujun9972 译者：unigeorge 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
cron 定时器是一个可以按照计划自动运行命令的工具。cron 定时器是一个可以按照计划自动运行命令的工具。定时器作业称为 cronjob，创建于 crontab 文件中。这是用户自动操作电脑的最简单也是最古老的方法。创建一个 cronjob要创建一个 cronjob，你可以使用 crontab 命令，并添加 -e 选项：$ crontab -e 这将使用默认的文本编辑器打开 crontab。如需指定文本编辑器，请使用 EDITOR 环境变量：$ EDITOR=nano crontab -e Cron 语法如需调度一个 cronjob，你需要提供给计算机你想要执行的命令，然后提供一个 cron 表达式。cron 表达式在命令调度时运行：分钟（0 到 59）小时（0 到 23, 0 代表午夜执行）日期（1 到 31）月份（1 到 12）星期（0 到 6, 星期天是 0）星号 （*） 代表的是“每一个”。例如，下面的表达式在每月每日每小时的 0 分钟运行备份脚本：/opt/backup.sh 0 * * * * 下面的表达式在周日的凌晨 3:30 运行备份脚本：/opt/backup.sh 30 3 * * 0 简写语法现代的 cron 支持简化的宏，而不是 cron 表达式：@hourly 在每天的每小时的 0 分运行@daily 在每天的 0 时 0 分运行@weekly 在周日的 0 时 0 分运行@monthly 在每月的第一天的 0 时 0 分运行例如，下面的 crontab 命令在每天的 0 时运行备份脚本：/opt/backup.sh @daily 如何停止一个 cronjob一旦你开始了一个 cronjob，它就会永远按照计划运行。想要在启动后停止 cronjob，你必须编辑 crontab，删除触发该作业的命令行，然后保存文件。$ EDITOR=nano crontab -e 如需停止一个正在运行的作业，可以 使用标准的 Linux 进程命令 来停止一个正在运行的进程。它是自动的一旦你编写完 crontab，保存了文件并且退出了编辑器。你的 cronjob 就已经被调度了，剩下的工作都交给 cron 完成。via: https://opensource.com/article/21/7/cron-linux作者：Seth Kenlon 选题：lujun9972 译者：perfiffer 校对：turbokernel本文由 LCTT 原创编译，Linux中国 荣誉推出
systemd 提供定时器有一段时间了，定时器替代了 cron 功能，这一特性值得看看。本文将向你介绍在系统启动后如何使用 systemd 中的定时器来运行任务，并在此后重复运行。这不是对 systemd 的全面讨论，只是对此特性的一个介绍。快速回顾：cron、anacron 与 systemdcron 可以以几分钟到几个月或更长时间的粒度调度运行一个任务。设置起来相对简单，它只需要一个配置文件。虽然配置过程有些深奥，但一般用户也可以使用。然而，如果你的系统在需要执行的时间没有运行，那么 cron 会失败。anacron 克服了“系统没有运行”的问题。它确保任务将在你的系统再次启动时执行。虽然它旨在给管理员使用，但有些系统允许普通用户访问 anacron。但是，anacron 的执行频率不能低于每天一次。cron 和 anacron 都存在执行上下文一致性的问题。必须注意任务运行时有效的环境与测试时使用的环境完全相同。必须提供相同的 shell、环境变量和路径。这意味着测试和调试有时会很困难。systemd 定时器提供了 cron 和 anacron 二者的优点，允许调度到分钟粒度。确保在系统再次运行时执行任务，即使在预期的执行时间内系统处于关闭状态。它对所有用户都可用。你可以在它将要运行的环境中测试和调试执行。但是，它的配置更加复杂，至少需要两个配置文件。如果你的 cron 和 anacron 配置可以很好地为你服务，那么可能没有理由改变。但是 systemd 至少值得研究，因为它可以简化任何当前的 cron/anacron 工作方式。配置systemd 定时器执行功能至少需要两个文件。这两个是“ 定时器单元 timer unit ”和“ 服务单元 service unit ”。（其执行的）“动作”不仅仅是简单的命令，你还需要一个“作业”文件或脚本来执行必要的功能。定时器单元文件定义调度表，而服务单元文件定义执行的任务。有关的更多详细信息请参考 man systemd.timer 中提供的 .timer 单元。服务单元的详细信息可在 man systemd.service 中找到。单元文件存放在几个位置（在手册页中有列出）。然而，对于普通用户来说，最容易找到的位置可能是 ~/.config/systemd/user。请注意，这里的 user 是字符串 user。示例此示例是一个创建用户调度作业而不是（以 root 用户身份运行的）系统调度作业的简单示例。它将消息、日期和时间打印到文件中。1、首先创建一个执行任务的 shell 脚本。在你的本地 bin 目录中创建它，例如在 ~/bin/schedule-test.sh 中。创建文件：touch ~/bin/schedule-test.sh 然后将以下内容添加到你刚刚创建的文件中：#!/bin/sh echo "This is only a test: $(date)" >> "$HOME/schedule-test-output.txt" 记住赋予你的 shell 脚本执行权限。2、创建 .service 单元调用上面的脚本。在以下位置创建目录与文件：~/.config/systemd/user/schedule-test.service：[Unit] Description=A job to test the systemd scheduler [Service] Type=simple ExecStart=/home/<user>/bin/schedule-test.sh [Install] WantedBy=default.target 请注意 <user> 应该是你的家目录地址，但是单元文件路径名中的 user 实际上是字符串 user。ExecStart 应该提供一个没有变量的绝对地址。例外情况是，对于用户单元文件，你可以用 %h 替换 $HOME。换句话说，你可以使用:ExecStart=%h/bin/schedule-test.sh 这仅用于用户单元文件，而不适用于系统服务，因为在系统环境中运行时 %h 总是返回 /root。其他特殊符号可在 man systemd.unit 的 SPECIFIERS 中找到。因为它超出了本文的范围，所以这就是我们目前需要了解的关于特殊符号的全部内容。3、创建一个 .timer 单元文件，该文件实际上调度你创建的 .service 单元文件。在 .service 单元文件相同位置创建它：~/.config/systemd/user/schedule-test.timer。请注意，文件名仅在扩展名上有所不同，例如一个是 .service，一个是 .timer。[Unit] Description=Schedule a message every 1 minute RefuseManualStart=no # Allow manual starts RefuseManualStop=no # Allow manual stops [Timer] #Execute job if it missed a run due to machine being off Persistent=true #Run 120 seconds after boot for the first time OnBootSec=120 #Run every 1 minute thereafter OnUnitActiveSec=60 #File describing job to execute Unit=schedule-test.service [Install] WantedBy=timers.target 请注意，这个 .timer 单元文件使用了 OnUnitActiveSec 来指定调度表。OnCalendar 选项更加灵活。例如:# run on the minute of every minute every hour of every day OnCalendar=*-*-* *:*:00 # run on the hour of every hour of every day OnCalendar=*-*-* *:00:00 # run every day OnCalendar=*-*-* 00:00:00 # run 11:12:13 of the first or fifth day of any month of the year # 2012, but only if that day is a Thursday or Friday OnCalendar=Thu,Fri 2012-*-1,5 11:12:13 有关 OnCalendar 的更多信息参见 这里。4、所有的部件都已就位，但你应该进行测试，以确保一切正常。首先，启用该用户服务:$ systemctl --user enable schedule-test.service 这将导致类似如下的输出:Created symlink /home/<user>/.config/systemd/user/default.target.wants/schedule-test.service → /home/<user>/.config/systemd/user/schedule-test.service. 现在执行测试工作：$ systemctl --user start schedule-test.service 检查你的输出文件（$HOME/schedule-test-output.txt），确保你的脚本运行正常。应该只有一个条目，因为我们还没有启动定时器。必要时进行调试。如果你需要更改 .service 单元文件，而不是更改它调用的 shell 脚本，请不要忘记再次启用该服务。5、一旦作业正常运行，通过为服务启用、启动用户定时器来实时调度作业：$ systemctl --user enable schedule-test.timer $ systemctl --user start schedule-test.timer 请注意，你已经在上面的步骤 4 中启动、启用了服务，因此只需要为它启用、启动定时器。enable 命令会产生如下输出：Created symlink /home/<user>/.config/systemd/user/timers.target.wants/schedule-test.timer → /home/<user>/.config/systemd/user/schedule-test.timer. start 命令将只是返回命令行界面提示符。其他操作你可以检查和监控服务。如果你从系统服务收到错误，下面的第一个命令特别有用：$ systemctl --user status schedule-test $ systemctl --user list-unit-files 手动停止服务：$ systemctl --user stop schedule-test.service 永久停止并禁用定时器和服务，重新加载守护程序配置并重置任何失败通知：$ systemctl --user stop schedule-test.timer $ systemctl --user disable schedule-test.timer $ systemctl --user stop schedule-test.service $ systemctl --user disable schedule-test.service $ systemctl --user daemon-reload $ systemctl --user reset-failed 总结本文以 systemd 定时器为出发点，但是 systemd 的内容远不止于此。这篇文章应该为你提供一个基础。你可以从 Fedora Magazine systemd 系列 开始探索更多。参考更多阅读：man systemd.timerman systemd.serviceUse systemd timers instead of cronjobsUnderstanding and administering systemdhttps://opensource.com/ 内有 systemd 速查表via: https://fedoramagazine.org/systemd-timers-for-scheduling-tasks/作者：Richard England 选题：lujun9972 译者：dcoliversun 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
cron 是一个调度守护进程，它以指定的时间间隔执行任务，这些任务称为 corn 作业，主要用于自动执行系统维护或管理任务。例如，你可以设置一个 cron 作业来自动执行重复的任务，比如备份数据库或数据，使用最新的安全补丁更新系统，检查磁盘空间使用情况，发送电子邮件等等。 cron 作业可以按分钟、小时、日、月、星期或它们的任意组合运行。cron 的一些优点以下是使用 cron 作业的一些优点：你可以更好地控制作业的运行时间。例如，你可以精确到分钟、小时、天等。它消除了为循环任务逻辑而去写代码的需要，当你不再需要执行任务时，可以直接关闭它。作业在不执行时不会占用内存，因此你可以节省内存分配。如果一个作业执行失败并由于某种原因退出，它将在适当的时间再次运行。安装 cron 守护进程幸运的是，Fedora Linux 预先配置了运行重要的系统任务来保持系统更新，有几个实用程序可以运行任务例如 cron、anacron、at 和 batch 。本文只关注 cron 实用程序的安装。cron 和 cronie 包一起安装，cronie 包也提供 cron 服务。要确定软件包是否已经存在，使用 rpm 命令：$ rpm -q cronie Cronie-1.5.2-4.el8.x86_64 如果安装了 cronie ，它将返回 cronie 包的全名。如果你的系统中没有安装，则会显示未安装。使用以下命令安装：$ dnf install cronie 运行 cron 守护进程cron 作业由 crond 服务来执行，它会读取配置文件中的信息。在将作业添加到配置文件之前，必须启动 crond 服务，或者安装它。什么是 crond 呢？crond 是 cron 守护程序的简称。要确定 crond 服务是否正在运行，输入以下命令：$ systemctl status crond.service ● crond.service - Command Scheduler Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor pre> Active: active (running) since Sat 2021-03-20 14:12:35 PDT; 1 day 21h ago Main PID: 1110 (crond) 如果你没有看到类似的内容 Active: active (running) since…，你需要启动 crond 守护进程。要在当前会话中运行 crond 服务，输入以下命令：$ systemctl run crond.service 将其配置为开机自启动，输入以下命令：$ systemctl enable crond.service 如果出于某种原因，你希望停止 crond 服务，按以下方式使用 stop 命令：$ systemctl stop crond.service 要重新启动它，只需使用 restart 命令：$ systemctl restart crond.service 定义一个 cron 作业cron 配置以下是一个 cron 作业的配置细节示例。它定义了一个简单的 cron 作业，将 git master 分支的最新更改拉取到克隆的仓库中：*/59 * * * * username cd /home/username/project/design && git pull origin master 主要有两部分：第一部分是 */59 * * * *。这表明计时器设置为第 59 分钟执行一次。（LCTT 译注：原文此处有误。）该行的其余部分是命令，因为它将从命令行运行。 在此示例中，命令本身包含三个部分：作业将以用户 username 的身份运行它将切换到目录 /home/username/project/design运行 git 命令拉取 master 分支中的最新更改时间语法如上所述，时间信息是 cron 作业字符串的第一部分，如上所属。它决定了 cron 作业运行的频率和时间。它按以下顺序包括 5 个部分：分钟小时一个月中的某天月份一周中的某天下面是一种更图形化的方式来解释语法： .--------------- 分钟 (0 - 59) | .------------- 小时 (0 - 23) | | .---------- 一月中的某天 (1 - 31) | | | .------- 月份 (1 - 12) 或 jan、feb、mar、apr … | | | | .---- 一周中的某天 (0-6) (周日=0 或 7) | | | | | 或 sun、mon、tue、wed、thr、fri、sat | | | | | * * * * * user-name command-to-be-executed 星号的使用星号（*）可以用来替代数字，表示该位置的所有可能值。例如，分钟位置上的星号会使它每分钟运行一次。以下示例可能有助于更好地理解语法。这个 cron 作业将每分钟运行一次：* * * * [command] 斜杠表示分钟的间隔数。下面的示例将每小时运行 12 次，即每 5 分钟运行一次：*/5 * * * * [command] 下一个示例将每月的第二天午夜（例如 1 月 2 日凌晨 12:00，2 月 2 日凌晨 12:00 等等）：0 0 2 * * [command] （LCTT 译注：关于 cron 时间格式，还有更多格式符号，此处没有展开）使用 crontab 创建一个 cron 作业cron 作业会在后台运行，它会不断检查 /etc/crontab 文件和 /etc/cron.*/ 以及 /var/spool/cron/ 目录。每个用户在 /var/spool/cron/ 中都有一个唯一的 crontab 文件。不应该直接编辑这些 cron 文件。crontab 命令是用于创建、编辑、安装、卸载和列出 cron 作业的方法。更酷的是，在创建新文件或编辑现有文件后，你无需重新启动 cron。$ crontab -e 这将打开你现有的 crontab 文件，或者创建一个。调用 crontab -e 时，默认情况下会使用 vi 编辑器。注意：要使用 Nano 编辑 crontab 文件，可以设置 EDITOR=nano 环境变量。使用 -l 选项列出所有 cron 作业。如果需要，使用 -u 选项指定一个用户。$ crontab -l $ crontab -u username -l 使用以下命令删除所有 cron 作业：$ crontab -r 要删除特定用户的作业，你必须以 root 用户身份运行以下命令：$ crontab -r -u username 感谢你的阅读。cron 作业看起来可能只是系统管理员的工具，但它实际上与许多 Web 应用程序和用户任务有关。参考Fedora Linux 文档的 自动化任务via: https://fedoramagazine.org/scheduling-tasks-with-cron/作者：Darshna Das 选题：lujun9972 译者：MjSeven 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
定时器提供了比 cron 作业更为细粒度的事件控制。我正在致力于将我的 cron 作业迁移到 systemd 定时器上。我已经使用定时器多年了，但通常来说，我的学识只足以支撑我当前的工作。但在我研究 systemd 系列 的过程中，我发现 systemd 定时器有一些非常有意思的能力。与 cron 作业类似，systemd 定时器可以在特定的时间间隔触发事件（shell 脚本和程序），例如每天一次或在一个月中的特定某一天（或许只有在周一生效），或在从上午 8 点到下午 6 点的工作时间内每隔 15 分钟一次。定时器也可以做到 cron 作业无法做到的一些事情。举个例子，定时器可以在特定事件发生后的一段时间后触发一段脚本或者程序去执行，例如开机、启动、上个任务完成，甚至于定时器调用的上个服务单元的完成的时刻。操作系统维护的计时器当在一个新系统上安装 Fedora 或者是任意一个基于 systemd 的发行版时，作为系统维护过程的一部分，它会在 Linux 宿主机的后台中创建多个定时器。这些定时器会触发事件来执行必要的日常维护任务，比如更新系统数据库、清理临时目录、轮换日志文件，以及更多其他事件。作为示例，我会查看一些我的主要工作站上的定时器，通过执行 systemctl status *timer 命令来展示主机上的所有定时器。星号的作用与文件通配相同，所以这个命令会列出所有的 systemd 定时器单元。[root@testvm1 ~]# systemctl status *timer ● mlocate-updatedb.timer - Updates mlocate database every day Loaded: loaded (/usr/lib/systemd/system/mlocate-updatedb.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Fri 2020-06-05 00:00:00 EDT; 15h left Triggers: ● mlocate-updatedb.service Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Updates mlocate database every day. ● logrotate.timer - Daily rotation of log files Loaded: loaded (/usr/lib/systemd/system/logrotate.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Fri 2020-06-05 00:00:00 EDT; 15h left Triggers: ● logrotate.service Docs: man:logrotate(8) man:logrotate.conf(5) Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Daily rotation of log files. ● sysstat-summary.timer - Generate summary of yesterday's process accounting Loaded: loaded (/usr/lib/systemd/system/sysstat-summary.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Fri 2020-06-05 00:07:00 EDT; 15h left Triggers: ● sysstat-summary.service Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Generate summary of yesterday's process accounting. ● fstrim.timer - Discard unused blocks once a week Loaded: loaded (/usr/lib/systemd/system/fstrim.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Mon 2020-06-08 00:00:00 EDT; 3 days left Triggers: ● fstrim.service Docs: man:fstrim Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Discard unused blocks once a week. ● sysstat-collect.timer - Run system activity accounting tool every 10 minutes Loaded: loaded (/usr/lib/systemd/system/sysstat-collect.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Thu 2020-06-04 08:50:00 EDT; 41s left Triggers: ● sysstat-collect.service Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Run system activity accounting tool every 10 minutes. ● dnf-makecache.timer - dnf makecache --timer Loaded: loaded (/usr/lib/systemd/system/dnf-makecache.timer; enabled; vendor preset: enabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Thu 2020-06-04 08:51:00 EDT; 1min 41s left Triggers: ● dnf-makecache.service Jun 02 08:02:33 testvm1.both.org systemd[1]: Started dnf makecache –timer. ● systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-clean.timer; static; vendor preset: disabled) Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago Trigger: Fri 2020-06-05 08:19:00 EDT; 23h left Triggers: ● systemd-tmpfiles-clean.service Docs: man:tmpfiles.d(5) man:systemd-tmpfiles(8) Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Daily Cleanup of Temporary Directories. 每个定时器至少有六行相关信息：定时器的第一行有定时器名字和定时器目的的简短介绍第二行展示了定时器的状态，是否已加载，定时器单元文件的完整路径以及预设信息。第三行指明了其活动状态，包括该定时器激活的日期和时间。第四行包括了该定时器下次被触发的日期和时间和距离触发的大概时间。第五行展示了被定时器触发的事件或服务名称。部分（不是全部）systemd 单元文件有相关文档的指引。我虚拟机上输出中有三个定时器有文档指引。这是一个很好（但非必要）的信息。最后一行是计时器最近触发的服务实例的日志条目。你也许有一些不一样的定时器，取决于你的主机。创建一个定时器尽管我们可以解构一个或多个现有的计时器来了解其工作原理，但让我们创建我们自己的 服务单元 和一个定时器去触发它。为了保持简单，我们将使用一个相当简单的例子。当我们完成这个实验之后，就能更容易理解其他定时器的工作原理以及发现它们正在做什么。首先，创建一个运行基础东西的简单的服务，例如 free 命令。举个例子，你可能想定时监控空余内存。在 /etc/systemd/system 目录下创建如下的 myMonitor.server 单元文件。它不需要是可执行文件：# This service unit is for testing timer units # By David Both # Licensed under GPL V2 # [Unit] Description=Logs system statistics to the systemd journal Wants=myMonitor.timer [Service] Type=oneshot ExecStart=/usr/bin/free [Install] WantedBy=multi-user.target 这大概是你能创建的最简单的服务单元了。现在我们查看一下服务状态同时测试一下服务单元确保它和我们预期一样可用。[root@testvm1 system]# systemctl status myMonitor.service ● myMonitor.service - Logs system statistics to the systemd journal Loaded: loaded (/etc/systemd/system/myMonitor.service; disabled; vendor preset: disabled) Active: inactive (dead) [root@testvm1 system]# systemctl start myMonitor.service [root@testvm1 system]# 输出在哪里呢？默认情况下，systemd 服务单元执行程序的标准输出（STDOUT）会被发送到系统日志中，它保留了记录供现在或者之后（直到某个时间点）查看。（在本系列的后续文章中，我将介绍系统日志的记录和保留策略）。专门查看你的服务单元的日志，而且只针对今天。-S 选项，即 --since 的缩写，允许你指定 journalctl 工具搜索条目的时间段。这并不代表你不关心过往结果 —— 在这个案例中，不会有过往记录 —— 如果你的机器以及运行了很长时间且堆积了大量的日志，它可以缩短搜索时间。[root@testvm1 system]# journalctl -S today -u myMonitor.service -- Logs begin at Mon 2020-06-08 07:47:20 EDT, end at Thu 2020-06-11 09:40:47 EDT. -- Jun 11 09:12:09 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal... Jun 11 09:12:09 testvm1.both.org free[377966]: total used free shared buff/cache available Jun 11 09:12:09 testvm1.both.org free[377966]: Mem: 12635740 522868 11032860 8016 1080012 11821508 Jun 11 09:12:09 testvm1.both.org free[377966]: Swap: 8388604 0 8388604 Jun 11 09:12:09 testvm1.both.org systemd[1]: myMonitor.service: Succeeded. [root@testvm1 system]# 由服务触发的任务可以是单个程序、一组程序或者是一个脚本语言写的脚本。通过在 myMonitor.service 单元文件里的 [Service] 块末尾中添加如下行可以为服务添加另一个任务：ExecStart=/usr/bin/lsblk 再次启动服务，查看日志检查结果，结果应该看上去像这样。你应该在日志中看到两条命令的结果输出：Jun 11 15:42:18 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal... Jun 11 15:42:18 testvm1.both.org free[379961]: total used free shared buff/cache available Jun 11 15:42:18 testvm1.both.org free[379961]: Mem: 12635740 531788 11019540 8024 1084412 11812272 Jun 11 15:42:18 testvm1.both.org free[379961]: Swap: 8388604 0 8388604 Jun 11 15:42:18 testvm1.both.org lsblk[379962]: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT Jun 11 15:42:18 testvm1.both.org lsblk[379962]: sda 8:0 0 120G 0 disk Jun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─sda1 8:1 0 4G 0 part /boot Jun 11 15:42:18 testvm1.both.org lsblk[379962]: └─sda2 8:2 0 116G 0 part Jun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─VG01-root 253:0 0 5G 0 lvm / Jun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─VG01-swap 253:1 0 8G 0 lvm [SWAP] Jun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─VG01-usr 253:2 0 30G 0 lvm /usr Jun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─VG01-tmp 253:3 0 10G 0 lvm /tmp Jun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─VG01-var 253:4 0 20G 0 lvm /var Jun 11 15:42:18 testvm1.both.org lsblk[379962]: └─VG01-home 253:5 0 10G 0 lvm /home Jun 11 15:42:18 testvm1.both.org lsblk[379962]: sr0 11:0 1 1024M 0 rom Jun 11 15:42:18 testvm1.both.org systemd[1]: myMonitor.service: Succeeded. Jun 11 15:42:18 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal. 现在你知道了你的服务可以按预期工作了，在 /etc/systemd/system 目录下创建 myMonitor.timer 定时器单元文件，添加如下代码：# This timer unit is for testing # By David Both # Licensed under GPL V2 # [Unit] Description=Logs some system statistics to the systemd journal Requires=myMonitor.service [Timer] Unit=myMonitor.service OnCalendar=*-*-* *:*:00 [Install] WantedBy=timers.target 在 myMonitor.timer 文件中的 OnCalendar 时间格式，*-*-* *:*:00，应该会每分钟触发一次定时器去执行 myMonitor.service 单元。我会在文章的后面进一步探索 OnCalendar 设置。到目前为止，在服务被计时器触发运行时观察与之有关的日志记录。你也可以跟踪计时器，跟踪服务可以让你接近实时的看到结果。执行 journalctl 时带上 -f 选项：[root@testvm1 system]# journalctl -S today -f -u myMonitor.service -- Logs begin at Mon 2020-06-08 07:47:20 EDT. -- 执行但是不启用该定时器，看看它运行一段时间后发生了什么：[root@testvm1 ~]# systemctl start myMonitor.service [root@testvm1 ~]# 一条结果立即就显示出来了，下一条大概在一分钟后出来。观察几分钟日志，看看你有没有跟我发现同样的事情：[root@testvm1 system]# journalctl -S today -f -u myMonitor.service -- Logs begin at Mon 2020-06-08 07:47:20 EDT. -- Jun 13 08:39:18 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal... Jun 13 08:39:18 testvm1.both.org systemd[1]: myMonitor.service: Succeeded. Jun 13 08:39:19 testvm1.both.org free[630566]: total used free shared buff/cache available Jun 13 08:39:19 testvm1.both.org free[630566]: Mem: 12635740 556604 10965516 8036 1113620 11785628 Jun 13 08:39:19 testvm1.both.org free[630566]: Swap: 8388604 0 8388604 Jun 13 08:39:18 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal. Jun 13 08:39:19 testvm1.both.org lsblk[630567]: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT Jun 13 08:39:19 testvm1.both.org lsblk[630567]: sda 8:0 0 120G 0 disk Jun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─sda1 8:1 0 4G 0 part /boot Jun 13 08:39:19 testvm1.both.org lsblk[630567]: └─sda2 8:2 0 116G 0 part Jun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─VG01-root 253:0 0 5G 0 lvm / Jun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─VG01-swap 253:1 0 8G 0 lvm [SWAP] Jun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─VG01-usr 253:2 0 30G 0 lvm /usr Jun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─VG01-tmp 253:3 0 10G 0 lvm /tmp Jun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─VG01-var 253:4 0 20G 0 lvm /var Jun 13 08:39:19 testvm1.both.org lsblk[630567]: └─VG01-home 253:5 0 10G 0 lvm /home Jun 13 08:39:19 testvm1.both.org lsblk[630567]: sr0 11:0 1 1024M 0 rom Jun 13 08:40:46 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal... Jun 13 08:40:46 testvm1.both.org free[630572]: total used free shared buff/cache available Jun 13 08:40:46 testvm1.both.org free[630572]: Mem: 12635740 555228 10966836 8036 1113676 11786996 Jun 13 08:40:46 testvm1.both.org free[630572]: Swap: 8388604 0 8388604 Jun 13 08:40:46 testvm1.both.org lsblk[630574]: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT Jun 13 08:40:46 testvm1.both.org lsblk[630574]: sda 8:0 0 120G 0 disk Jun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─sda1 8:1 0 4G 0 part /boot Jun 13 08:40:46 testvm1.both.org lsblk[630574]: └─sda2 8:2 0 116G 0 part Jun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─VG01-root 253:0 0 5G 0 lvm / Jun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─VG01-swap 253:1 0 8G 0 lvm [SWAP] Jun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─VG01-usr 253:2 0 30G 0 lvm /usr Jun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─VG01-tmp 253:3 0 10G 0 lvm /tmp Jun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─VG01-var 253:4 0 20G 0 lvm /var Jun 13 08:40:46 testvm1.both.org lsblk[630574]: └─VG01-home 253:5 0 10G 0 lvm /home Jun 13 08:40:46 testvm1.both.org lsblk[630574]: sr0 11:0 1 1024M 0 rom Jun 13 08:40:46 testvm1.both.org systemd[1]: myMonitor.service: Succeeded. Jun 13 08:40:46 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal. Jun 13 08:41:46 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal... Jun 13 08:41:46 testvm1.both.org free[630580]: total used free shared buff/cache available Jun 13 08:41:46 testvm1.both.org free[630580]: Mem: 12635740 553488 10968564 8036 1113688 11788744 Jun 13 08:41:46 testvm1.both.org free[630580]: Swap: 8388604 0 8388604 Jun 13 08:41:47 testvm1.both.org lsblk[630581]: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT Jun 13 08:41:47 testvm1.both.org lsblk[630581]: sda 8:0 0 120G 0 disk Jun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─sda1 8:1 0 4G 0 part /boot Jun 13 08:41:47 testvm1.both.org lsblk[630581]: └─sda2 8:2 0 116G 0 part Jun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─VG01-root 253:0 0 5G 0 lvm / Jun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─VG01-swap 253:1 0 8G 0 lvm [SWAP] Jun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─VG01-usr 253:2 0 30G 0 lvm /usr Jun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─VG01-tmp 253:3 0 10G 0 lvm /tmp Jun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─VG01-var 253:4 0 20G 0 lvm /var Jun 13 08:41:47 testvm1.both.org lsblk[630581]: └─VG01-home 253:5 0 10G 0 lvm /home Jun 13 08:41:47 testvm1.both.org lsblk[630581]: sr0 11:0 1 1024M 0 rom Jun 13 08:41:47 testvm1.both.org systemd[1]: myMonitor.service: Succeeded. Jun 13 08:41:47 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal. 别忘了检查下计时器和服务的状态。你在日志里大概至少注意到两件事。第一，你不需要特地做什么来让 myMonitor.service 单元中 ExecStart 触发器产生的 STDOUT 存储到日志里。这都是用 systemd 来运行服务的一部分功能。然而，它确实意味着你需要小心对待服务单元里面执行的脚本和它们能产生多少 STDOUT。第二，定时器并不是精确在每分钟的 :00 秒执行的，甚至每次执行的时间间隔都不是刚好一分钟。这是特意的设计，但是有必要的话可以改变这种行为（如果只是它挑战了你的系统管理员的敏感神经）。这样设计的初衷是为了防止多个服务在完全相同的时刻被触发。举个例子，你可以用例如 Weekly，Daily 等时间格式。这些快捷写法都被定义为在某一天的 00:00:00 执行。当多个定时器都这样定义的话，有很大可能它们会同时执行。systemd 定时器被故意设计成在规定时间附近随机波动的时间点触发，以避免同一时间触发。它们在一个时间窗口内半随机触发，时间窗口开始于预设的触发时间，结束于预设时间后一分钟。根据 systemd.timer 的手册页，这个触发时间相对于其他已经定义的定时器单元保持在稳定的位置。你可以在日志条目中看到，定时器在启动后立即触发，然后在每分钟后的 46 或 47 秒触发。大部分情况下，这种概率抖动的定时器是没事的。当调度类似执行备份的任务，只需要它们在下班时间运行，这样是没问题的。系统管理员可以选择确定的开始时间来确保不和其他任务冲突，例如 01:05:00 这样典型的 cron 作业时间，但是有很大范围的时间值可以满足这一点。在开始时间上的一个分钟级别的随机往往是无关紧要的。然而，对某些任务来说，精确的触发时间是个硬性要求。对于这类任务，你可以向单元文件的 Timer 块中添加如下声明来指定更高的触发时间跨度精确度（精确到微秒以内）：AccuracySec=1us 时间跨度可用于指定所需的精度，以及定义重复事件或一次性事件的时间跨度。它能识别以下单位：usec，us，µsmsec，msseconds，second，sec，sminutes，minute，min，mhours，hour，hr，hdays，day，dweeks，week，wmonths，month，M（定义为 30.44 天）years，year，y（定义为 365.25 天）所有 /usr/lib/systemd/system 中的定时器都指定了一个更宽松的时间精度，因为精准时间没那么重要。看看这些系统创建的定时器的时间格式：[root@testvm1 system]# grep Accur /usr/lib/systemd/system/*timer /usr/lib/systemd/system/fstrim.timer:AccuracySec=1h /usr/lib/systemd/system/logrotate.timer:AccuracySec=1h /usr/lib/systemd/system/logwatch.timer:AccuracySec=12h /usr/lib/systemd/system/mlocate-updatedb.timer:AccuracySec=24h /usr/lib/systemd/system/raid-check.timer:AccuracySec=24h /usr/lib/systemd/system/unbound-anchor.timer:AccuracySec=24h [root@testvm1 system]# 看下 /usr/lib/systemd/system 目录下部分定时器单元文件的完整内容，看看它们是如何构建的。在本实验中不必让这个定时器在启动时激活，但下面这个命令可以设置开机自启：[root@testvm1 system]# systemctl enable myMonitor.timer 你创建的单元文件不需要是可执行的。你同样不需要启用服务，因为它是被定时器触发的。如果你需要的话，你仍然可以在命令行里手动触发该服务单元。尝试一下，然后观察日志。关于定时器精度、事件时间规格和触发事件的详细信息，请参见 systemd.timer 和 systemd.time 的手册页。定时器类型systemd 定时器还有一些在 cron 中找不到的功能，cron 只在确定的、重复的、具体的日期和时间触发。systemd 定时器可以被配置成根据其他 systemd 单元状态发生改变时触发。举个例子，定时器可以配置成在系统开机、启动后，或是某个确定的服务单元激活之后的一段时间被触发。这些被称为单调计时器。“单调”指的是一个持续增长的计数器或序列。这些定时器不是持久的，因为它们在每次启动后都会重置。表格 1 列出了一些单调定时器以及每个定时器的简短定义，同时有 OnCalendar 定时器，这些不是单调的，它们被用于指定未来有可能重复的某个确定时间。这个信息来自于 systemd.timer 的手册页，有一些不重要的修改。定时器单调性定义OnActiveSec=X定义了一个与定时器被激活的那一刻相关的定时器。OnBootSec=X定义了一个与机器启动时间相关的计时器。OnStartupSec=X定义了一个与服务管理器首次启动相关的计时器。对于系统定时器来说，这个定时器与 OnBootSec= 类似，因为系统服务管理器在机器启动后很短的时间后就会启动。当以在每个用户服务管理器中运行的单元进行配置时，它尤其有用，因为用户的服务管理器通常在首次登录后启动，而不是机器启动后。OnUnitActiveSec=X定义了一个与将要激活的定时器上次激活时间相关的定时器。OnUnitInactiveSec=X定义了一个与将要激活的定时器上次停用时间相关的定时器。OnCalendar= 定义了一个有日期事件表达式语法的实时（即时钟）定时器。查看 systemd.time(7) 的手册页获取更多与日历事件表达式相关的语法信息。除此以外，它的语义和 OnActiveSec= 类似。Table 1: systemd 定时器定义单调计时器可使用同样的简写名作为它们的时间跨度，即我们之前提到的 AccuracySec 表达式，但是 systemd 将这些名字统一转换成了秒。举个例子，比如你想规定某个定时器在系统启动后五天触发一次事件；它可能看起来像 OnBootSec=5d。如果机器启动于 2020-06-15 09:45:27，这个定时器会在 2020-06-20 09:45:27 或在这之后的一分钟内触发。日历事件格式日历事件格式是定时器在所需的重复时间触发的关键。我们开始看下一些 OnCalendar 设置一起使用的格式。与 crontab 中的格式相比，systemd 及其计时器使用的时间和日历格式风格不同。它比 crontab 更为灵活，而且可以使用类似 at 命令的方式允许模糊的日期和时间。它还应该足够熟悉使其易于理解。systemd 定时器使用 OnCalendar= 的基础格式是 DOW YYYY-MM-DD HH:MM:SS。DOW（星期几）是选填的，其他字段可以用一个星号（*）来匹配此位置的任意值。所有的日历时间格式会被转换成标准格式。如果时间没有指定，它会被设置为 00:00:00。如果日期没有指定但是时间指定了，那么下次匹配的时间可能是今天或者明天，取决于当前的时间。月份和星期可以使用名称或数字。每个单元都可以使用逗号分隔的列表。单元范围可以在开始值和结束值之间用 .. 指定。指定日期有一些有趣的选项，波浪号（~）可以指定月份的最后一天或者最后一天之前的某几天。/ 可以用来指定星期几作为修饰符。这里有几个在 OnCalendar 表达式中使用的典型时间格式例子。日期事件格式描述DOW YYYY-MM-DD HH:MM:SS *-*-* 00:15:30每年每月每天的 0 点 15 分 30 秒Weekly每个周一的 00:00:00Mon *-*-* 00:00:00同上Mon同上Wed 2020-*-*2020 年每个周三的 00:00:00Mon..Fri 2021-*-*2021 年的每个工作日（周一到周五）的 00:00:002022-6,7,8-1,15 01:15:002022 年 6、7、8 月的 1 到 15 号的 01:15:00Mon *-05~03每年五月份的下个周一同时也是月末的倒数第三天Mon..Fri *-08~04任何年份 8 月末的倒数第四天，同时也须是工作日*-05~03/2五月末的倒数第三天，然后 2 天后再来一次。每年重复一次。注意这个表达式使用了波浪号（~）。*-05-03/2五月的第三天，然后每两天重复一次直到 5 月底。注意这个表达式使用了破折号（-）。Table 2: OnCalendar 事件时间格式例子测试日历格式systemd 提供了一个绝佳的工具用于检测和测试定时器中日历时间事件的格式。systemd-analyze calendar 工具解析一个时间事件格式，提供标准格式和其他有趣的信息，例如下次“经过”（即匹配）的日期和时间，以及距离下次触发之前大概时间。首先，看看未来没有时间的日（注意 Next elapse 和 UTC 的时间会根据你当地时区改变）:[student@studentvm1 ~]$ systemd-analyze calendar 2030-06-17 Original form: 2030-06-17 Normalized form: 2030-06-17 00:00:00 Next elapse: Mon 2030-06-17 00:00:00 EDT (in UTC): Mon 2030-06-17 04:00:00 UTC From now: 10 years 0 months left [root@testvm1 system]# 现在添加一个时间，在这个例子中，日期和时间是当作无关的部分分开解析的：[root@testvm1 system]# systemd-analyze calendar 2030-06-17 15:21:16 Original form: 2030-06-17 Normalized form: 2030-06-17 00:00:00 Next elapse: Mon 2030-06-17 00:00:00 EDT (in UTC): Mon 2030-06-17 04:00:00 UTC From now: 10 years 0 months left Original form: 15:21:16 Normalized form: *-*-* 15:21:16 Next elapse: Mon 2020-06-15 15:21:16 EDT (in UTC): Mon 2020-06-15 19:21:16 UTC From now: 3h 55min left [root@testvm1 system]# 为了把日期和时间当作一个单元来分析，可以把它们包在引号里。你在定时器单元里 OnCalendar= 时间格式中使用的时候记得把引号去掉，否则会报错：[root@testvm1 system]# systemd-analyze calendar "2030-06-17 15:21:16" Normalized form: 2030-06-17 15:21:16 Next elapse: Mon 2030-06-17 15:21:16 EDT (in UTC): Mon 2030-06-17 19:21:16 UTC From now: 10 years 0 months left [root@testvm1 system]# 现在我们测试下 Table2 里的例子。我尤其喜欢最后一个：[root@testvm1 system]# systemd-analyze calendar "2022-6,7,8-1,15 01:15:00" Original form: 2022-6,7,8-1,15 01:15:00 Normalized form: 2022-06,07,08-01,15 01:15:00 Next elapse: Wed 2022-06-01 01:15:00 EDT (in UTC): Wed 2022-06-01 05:15:00 UTC From now: 1 years 11 months left [root@testvm1 system]# 让我们看一个例子，这个例子里我们列出了时间表达式的五个经过时间。[root@testvm1 ~]# systemd-analyze calendar --iterations=5 "Mon *-05~3" Original form: Mon *-05~3 Normalized form: Mon *-05~03 00:00:00 Next elapse: Mon 2023-05-29 00:00:00 EDT (in UTC): Mon 2023-05-29 04:00:00 UTC From now: 2 years 11 months left Iter. #2: Mon 2028-05-29 00:00:00 EDT (in UTC): Mon 2028-05-29 04:00:00 UTC From now: 7 years 11 months left Iter. #3: Mon 2034-05-29 00:00:00 EDT (in UTC): Mon 2034-05-29 04:00:00 UTC From now: 13 years 11 months left Iter. #4: Mon 2045-05-29 00:00:00 EDT (in UTC): Mon 2045-05-29 04:00:00 UTC From now: 24 years 11 months left Iter. #5: Mon 2051-05-29 00:00:00 EDT (in UTC): Mon 2051-05-29 04:00:00 UTC From now: 30 years 11 months left [root@testvm1 ~]# 这些应该为你提供了足够的信息去开始测试你的 OnCalendar 时间格式。systemd-analyze 工具可用于其他有趣的分析，我会在这个系列的下一篇文章来探索这些。总结systemd 定时器可以用于执行和 cron 工具相同的任务，但是通过按照日历和单调时间格式去触发事件的方法提供了更多的灵活性。虽然你为此次实验创建的服务单元通常是由定时器调用的，你也可以随时使用 systemctl start myMonitor.service 命令去触发它。可以在一个定时器中编写多个维护任务的脚本；它们可以是 Bash 脚本或者其他 Linux 程序。你可以通过触发定时器来运行所有的脚本来运行服务，也可以按照需要执行单独的脚本。我会在下篇文章中更加深入的探索 systemd 时间格式的用处。我还没有看到任何迹象表明 cron 和 at 将被废弃。我希望这种情况不会发生，因为至少 at 在执行一次性调度任务的时候要比 systemd 定时器容易的多。参考资料网上有大量的关于 systemd 的参考资料，但是大部分都有点简略、晦涩甚至有误导性。除了本文中提到的资料，下列的网页提供了跟多可靠且详细的 systemd 入门信息。Fedora 项目有一篇切实好用的 systemd 入门，它囊括了几乎所有你需要知道的关于如何使用 systemd 配置、管理和维护 Fedora 计算机的信息。Fedora 项目也有一个不错的 备忘录，交叉引用了过去 SystemV 命令和 systemd 命令做对比。关于 systemd 的技术细节和创建这个项目的原因，请查看 Freedesktop.org 上的 systemd 描述。Linux.com 的“更多 systemd 的乐趣”栏目提供了更多高级的 systemd 信息和技巧。此外，还有一系列深度的技术文章，是由 systemd 的设计者和主要实现者 Lennart Poettering 为 Linux 系统管理员撰写的。这些文章写于 2010 年 4 月至 2011 年 9 月间，但它们现在和当时一样具有现实意义。关于 systemd 及其生态的许多其他好文章都是基于这些文章：Rethinking PID 1systemd for Administrators，Part Isystemd for Administrators，Part IIsystemd for Administrators，Part IIIsystemd for Administrators，Part IVsystemd for Administrators，Part Vsystemd for Administrators，Part VIsystemd for Administrators，Part VIIsystemd for Administrators，Part VIIIsystemd for Administrators，Part IXsystemd for Administrators，Part Xsystemd for Administrators，Part XIvia: https://opensource.com/article/20/7/systemd-timers作者：David Both 选题：lujun9972 译者：tt67wq 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
与其手动执行重复性的任务，不如让 Linux 为你做。在 2021 年，人们有更多的理由喜欢 Linux。在这个系列中，我将分享使用 Linux 的 21 个不同理由。自动化是使用 Linux 的最佳理由之一。我最喜欢 Linux 的一个原因是它愿意为我做工作。我不想执行重复性的任务，这些任务会占用我的时间，或者容易出错，或者我可能会忘记，我安排 Linux 为我做这些工作。为自动化做准备“自动化”这个词既让人望而生畏，又让人心动。我发现用模块化的方式来处理它是有帮助的。1、你想实现什么？首先，要知道你想产生什么结果。你是要给图片加水印吗？从杂乱的目录中删除文件？执行重要数据的备份？为自己明确定义任务，这样你就知道自己的目标是什么。如果有什么任务是你发现自己每天都在做的，甚至一天一次以上，那么它可能是自动化的候选者。2、学习你需要的应用将大的任务分解成小的组件，并学习如何手动但以可重复和可预测的方式产生每个结果。在 Linux 上可以做的很多事情都可以用脚本来完成，但重要的是要认识到你当前的局限性。学习如何自动调整几张图片的大小，以便可以方便地通过电子邮件发送，与使用机器学习为你的每周通讯生成精心制作的艺术品之间有天壤之别。有的事你可以在一个下午学会，而另一件事可能要花上几年时间。然而，我们都必须从某个地方开始，所以只要从小做起，并时刻注意改进的方法。3、自动化在 Linux 上使用一个自动化工具来定期实现它。这就是本文介绍的步骤!要想自动化一些东西，你需要一个脚本来自动化一个任务。在测试时，最好保持简单，所以本文自动化的任务是在 /tmp 目录下创建一个名为 hello 的文件。#!/bin/sh touch /tmp/hello 将这个简单的脚本复制并粘贴到一个文本文件中，并将其命名为 example。Cron每个安装好的 Linux 系统都会有的内置自动化解决方案就是 cron 系统。Linux 用户往往把 cron 笼统地称为你用来安排任务的方法（通常称为 “cron 作业”），但有多个应用程序可以提供 cron 的功能。最通用的是 cronie；它的优点是，它不会像历史上为系统管理员设计的 cron 应用程序那样，假设你的计算机总是开着。验证你的 Linux 发行版提供的是哪个 cron 系统。如果不是 cronie，你可以从发行版的软件仓库中安装 cronie。如果你的发行版没有 cronie 的软件包，你可以使用旧的 anacron 软件包来代替。anacron 命令是包含在 cronie 中的，所以不管你是如何获得它的，你都要确保在你的系统上有 anacron 命令，然后再继续。anacron 可能需要管理员 root 权限，这取决于你的设置。$ which anacron /usr/sbin/anacron anacron 的工作是确保你的自动化作业定期执行。为了做到这一点，anacron 会检查找出最后一次运行作业的时间，然后检查你告诉它运行作业的频率。假设你将 anacron 设置为每五天运行一次脚本。每次你打开电脑或从睡眠中唤醒电脑时，anacron都会扫描其日志以确定是否需要运行作业。如果一个作业在五天或更久之前运行，那么 anacron 就会运行该作业。Cron 作业许多 Linux 系统都捆绑了一些维护工作，让 cron 来执行。我喜欢把我的工作与系统工作分开，所以我在我的主目录中创建了一个目录。具体来说，有一个叫做 ~/.local 的隐藏文件夹（“local” 的意思是它是为你的用户账户定制的，而不是为你的“全局”计算机系统定制的），所以我创建了子目录 etc/cron.daily 来作为 cron 在我的系统上的家目录。你还必须创建一个 spool 目录来跟踪上次运行作业的时间。$ mkdir -p ~/.local/etc/cron.daily ~/.var/spool/anacron 你可以把任何你想定期运行的脚本放到 ~/.local/etc/cron.daily 目录中。现在把 example 脚本复制到目录中，然后 用 chmod 命令使其可执行。$ cp example ~/.local/etc/cron.daily # chmod +x ~/.local/etc/cron.daily/example 接下来，设置 anacron 来运行位于 ~/.local/etc/cron.daily 目录下的任何脚本。anacron默认情况下，cron 系统的大部分内容都被认为是系统管理员的领域，因为它通常用于重要的底层任务，如轮换日志文件和更新证书。本文演示的配置是为普通用户设置个人自动化任务而设计的。要配置 anacron 来运行你的 cron 作业，请在 /.local/etc/anacrontab 创建一个配置文件：SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin 1 0 cron.mine run-parts /home/tux/.local/etc/cron.daily/ 这个文件告诉 anacron 每到新的一天（也就是每日），延迟 0 分钟后，就运行（run-parts）所有在 ~/.local/etc/cron.daily 中找到的可执行脚本。有时，会使用几分钟的延迟，这样你的计算机就不会在你登录后就被所有可能的任务冲击。不过这个设置适合测试。cron.mine 值是进程的一个任意名称。我称它为 cron.mine，但你也可以称它为 cron.personal 或 penguin 或任何你想要的名字。验证你的 anacrontab 文件的语法：$ anacron -T -t ~/.local/etc/anacrontab \ -S /home/tux/.var/spool/anacron 沉默意味着成功。在 .profile 中添加 anacron最后，你必须确保 anacron 以你的本地配置运行。因为你是以普通用户而不是 root 用户的身份运行 anacron，所以你必须将它引导到你的本地配置：告诉 anacron 要做什么的 anacrontab 文件，以及帮助 anacron 跟踪每一个作业最后一次执行是多少天的 spool 目录：anacron -fn -t /home/tux/.local/etc/anacrontab \ -S /home/tux/.var/spool/anacron -fn 选项告诉 anacron 忽略 时间戳，这意味着你强迫它无论如何都要运行你的 cron 作业。这完全是为了测试的目的。测试你的 cron 作业现在一切都设置好了，你可以测试作业了。从技术上讲，你可以在不重启的情况下进行测试，但重启是最有意义的，因为这就是设计用来处理中断和不规则的登录会话的。花点时间重启电脑、登录，然后寻找测试文件：$ ls /tmp/hello /tmp/hello 假设文件存在，那么你的示例脚本已经成功执行。现在你可以从 ~/.profile 中删除测试选项，留下这个作为你的最终配置。anacron -t /home/tux/.local/etc/anacrontab \ -S /home/tux/.var/spool/anacron 使用 anacron你已经配置好了你的个人自动化基础设施，所以你可以把任何你想让你的计算机替你管理的脚本放到 ~/.local/etc/cron.daily 目录下，它就会按计划运行。这取决于你希望作业运行的频率。示例脚本是每天执行一次。很明显，这取决于你的计算机在任何一天是否开机和醒着。如果你在周五使用电脑，但把它设置在周末，脚本就不会在周六和周日运行。然而，在周一，脚本会执行，因为 anacron 会知道至少有一天已经过去了。你可以在 ~/.local/etc 中添加每周、每两周、甚至每月的目录，以安排各种各样的间隔。要添加一个新的时间间隔：在 ~/.local/etc 中添加一个目录（例如 cron.weekly）。在 ~/.local/etc/anacrontab 中添加一行，以便在新目录下运行脚本。对于每周一次的间隔，其配置如下。7 0 cron.mine run-parts /home/tux/.local/etc/cron.weekly/（0 的值可以选择一些分钟数，以适当地延迟脚本的启动）。把你的脚本放在 cron.weekly 目录下。欢迎来到自动化的生活方式。它不会让人感觉到，但你将会变得更有效率。via: https://opensource.com/article/21/2/linux-automation作者：Seth Kenlon 选题：lujun9972 译者：wxy 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
at 命令可以很容易地安排 Linux 任务在你选择的任何时间或日期运行，让我们来看看它能为你做什么。当你希望命令或脚本在某个特定时间运行时，你不需要将手指放在键盘上盘旋等待按下回车键，或者是在特定时间坐在办公桌前。相反，你可以通过 at 命令来设置任务。在本文中，我们将研究如何使用 at 来安排任务，如何精确地选择任务希望运行的时间，以及如何使用 at 来查看安排运行的任务。at vs cron对于那些使用 cron 在 Linux 系统上安排任务的人来说，at 命令类似于 cron，因为你可以在选定的时间调度任务，但是 cron 用于定期运行的作业 —— 甚至是每年仅一次。大多数 cron 作业的频率都设置为每天、每周或每月运行一次，不过你可以控制运行的频率和时间。另一方面，at 命令用于仅运行一次的任务。想在午夜重启系统？没问题，只要你有适当的权限，at 可以为你完成此操作。如果你希望系统在每个星期六凌晨 2 点重启，那么改用 cron。使用 atat 命令很容易使用，只需记住几件事。一个简单使用 at 的例子类似于这样：$ at 5:00PM at> date >> thisfile at> <EOT>在输入 at 和应该运行命令的时间，at 会提示你在设定时间会运行该命令（此例中是 date 命令）。输入 ^D（Ctrl + d）来完成请求。假设我们在下午 5 点之前设置这个 at 命令，那么这个日期和时间将在当天下午 5 点添加到名为 thisfile 文件的末尾。否则，该命令将在第二天下午 5 点运行。与 at 命令进行交互时，可以输入多个命令。如果你要同时运行多个命令，只需输入多个命令行即可：$ at 6:22 warning: commands will be executed using /bin/sh at> echo first >> thisfile at> echo second >> thisfile at> <EOT>在上面的命令中，我们使用了一个普通的用户账户，将一些简单的文本添加到该用户主目录的文件中。如果在上午 6:22 之后运行这些命令，那么命令会在第二天运行，因为 6:22 表示上午 6:22。如果你想在下午 6:22 运行，使用 6:22 PM 或者 18:22。6:22 PM 这样也是可以工作的。你也可以通过使用 at 来安排命令在指定的日期或时间运行，例如 10:00AM April 15 2021 或 noon + 5 days（从今天起 5 天内的中午运行），以下是一些例子：at 6PM tomorrow at noon April 15 2021 at noon + 5 days at 9:15 + 1000 days在指定要运行的命令并按下 ^D 后，你会注意到 at 命令为每个请求分配了一个作业编号，这个数字将显示在 at 命令的作业队列中。$ at noon + 1000 days warning: commands will be executed using /bin/sh at> date >> thisfile at> <EOT> job 36 at Tue Dec 27 12:00:00 2022 <== job # is 36检查队列你可以使用 atq（at queue）命令来查看 at 作业队列：$ atq 32 Thu Apr 2 03:06:00 2020 a shs 35 Mon Apr 6 12:00:00 2020 a shs 36 Tue Dec 27 12:00:00 2022 a shs 34 Thu Apr 2 18:00:00 2020 a shs如果你需要取消队列中的一个作业，使用 atrm（at remove）命令和作业编号：$ atrm 32 $ atq 35 Mon Apr 6 12:00:00 2020 a shs 36 Tue Dec 27 12:00:00 2022 a shs 34 Thu Apr 2 18:00:00 2020 a shs你可以使用 at -c 命令来查看安排任务的详细信息，其它详细信息（活动的搜索路径等）也可以看到，但是输出的最后一行将显示计划运行的命令。$ at -c 36 | tail -6 cd /home/shs || { echo 'Execution directory inaccessible' >&2 exit 1 } date >> thisfile注意，该命令显示首先会测试是否可以通过 cd 命令进入用户目录。如果不可以，作业将退出并显示错误。如果可以，则运行在 at 中指定的命令。它将命令视为 “进入 /home/shs 或退出并显示错误”。以 root 身份运行作业要以 root 身份运行 at 作业，只需将 sudo 与你的 at 命令一起使用，如下所示：$ sudo at 8PM [sudo] password for shs: warning: commands will be executed using /bin/sh at> reboot now at> <EOT> job 37 at Wed Apr 1 16:00:00 2020注意，root 的任务以 root 作为执行者显示在队列中。35 Mon Apr 6 12:00:00 2020 a shs 36 Tue Dec 27 12:00:00 2022 a shs 37 Wed Apr 1 20:00:00 2020 a root <==运行脚本你还可以使用 at 命令来运行脚本，这里有一个例子：$ at 4:30PM warning: commands will be executed using /bin/sh at> bin/tryme at> <EOT>禁止使用 at 命令/etc/at.deny 文件提供了一种禁止用户使用 at 命令的方法。默认情况下，它可能会包含一个不允许的账户列表，例如 ftp 和 nobody。可以使用 /etc/at.allow 文件执行相反的操作，但是通常只配置 at.deny 文件。总结当你要安排一项一次性任务时，无论你是希望在今天下午或几年后运行，at 命令都是通用且易于使用的。via: https://www.networkworld.com/article/3535808/scheduling-tasks-on-linux-using-the-at-command.html作者：Sandra Henry-Stocker 选题：lujun9972 译者：MjSeven 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
如何使用 cron 任务在 Linux 中计划和自动化任务
有时，你可能需要定期或以预定的时间间隔执行任务。这些任务包括备份数据库、更新系统、执行定期重新引导等。这些任务称为 “cron 任务”。cron 任务用于“自动执行的任务”，它有助于简化重复的、有时是乏味的任务的执行。cron 是一个守护进程，可让你安排这些任务，然后按指定的时间间隔执行这些任务。在本教程中，你将学习如何使用 cron 来安排任务。crontab 文件crontab 即 “cron table”，是一个简单的文本文件，其中包含指定任务执行时间间隔的规则和命令。 crontab 文件分为两类：1）系统范围的 crontab 文件这些通常由需要 root 特权的 Linux 服务及关键应用程序使用。系统 crontab 文件位于 /etc/crontab 中，并且只能由 root 用户访问和编辑。通常用于配置系统范围的守护进程。crontab 文件的看起来类似如下所示：2）用户创建的 crontab 文件Linux 用户还可以在 crontab 命令的帮助下创建自己的 cron 任务。创建的 cron 任务将以创建它们的用户身份运行。所有 cron 任务都存储在 /var/spool/cron（对于 RHEL 和 CentOS 发行版）和 /var/spool/cron/crontabs（对于 Debian 和 Ubuntu 发行版）中，cron 任务使用创建该文件的用户的用户名列出。cron 守护进程在后台静默地检查 /etc/crontab 文件和 /var/spool/cron 及 /etc/cron.d*/ 目录。crontab 命令用于编辑 cron 文件。让我们看一下 crontab 文件的结构。crontab 文件剖析在继续之前，我们要首先探索 crontab 文件的格式。crontab 文件的基本语法包括 5 列，由星号表示，后跟要执行的命令。* * * * * command此格式也可以表示如下：m h d moy dow command或m h d moy dow /path/to/script让我们来解释一下每个条目m：代表分钟。范围是 0 到 59h：表示小时，范围是 0 到 23d：代表一个月中的某天，范围是 1 到 31moy：这是一年中的月份。范围是 1 到 12dow：这是星期几。范围是 0 到 6，其中 0 代表星期日command：这是要执行的命令，例如备份命令、重新启动和复制命令等管理 cron 任务看完 crontab 文件的结构之后，让我们看看如何创建、编辑和删除 cron 任务。创建 cron 任务要以 root 用户身份创建或编辑 cron 任务，请运行以下命令：# crontab -e要为另一个用户创建或安排 cron 任务，请使用以下语法：# crontab -u username -e例如，要以 Pradeep 用户身份运行 cron 任务，请发出以下命令：# crontab -u Pradeep -e如果该 crontab 文件尚不存在，那么你将打开一个空白文本文件。如果该 crontab 文件已经存在，则 -e 选项会让你编辑该文件，列出 crontab 文件要查看已创建的 cron 任务，只需传递 -l 选项：# crontab -l删除 crontab 文件要删除 cron 任务，只需运行 crontab -e 并删除所需的 cron 任务行，然后保存该文件。要删除所有的 cron 任务，请运行以下命令：# crontab -r然后，让我们看一下安排任务的不同方式。使用 crontab 安排任务示例如图所示，所有 cron 任务文件都带有 释伴 shebang 标头。#!/bin/bash这表示你正在使用的 shell，在这种情况下，即 bash shell。接下来，使用我们之前指定的 cron 任务条目指定要安排任务的时间间隔。要每天下午 12:30 重启系统，请使用以下语法：30 12 * * * /sbin/reboot要安排在凌晨 4:00 重启，请使用以下语法：0 4 * * * /sbin/reboot注：星号 * 用于匹配所有记录。要每天两次运行脚本（例如，凌晨 4:00 和下午 4:00），请使用以下语法：0 4,16 * * * /path/to/script要安排 cron 任务在每个星期五下午 5:00 运行，请使用以下语法：0 17 * * Fri /path/to/script或0 17 * * * 5 /path/to/script如果你希望每 30 分钟运行一次 cron 任务，请使用：*/30 * * * * /path/to/script要安排 cron 任务每 5 小时运行一次，请运行：* */5 * * * /path/to/script要在选定的日期（例如，星期三和星期五的下午 6:00）运行脚本，请执行以下操作：0 18 * * wed,fri /path/to/script要使用单个 cron 任务运行多个命令，请使用分号分隔任务，例如：* * * * * /path/to/script1 ; /path/to/script2使用特殊字符串节省编写 cron 任务的时间某些 cron 任务可以使用对应于特定时间间隔的特殊字符串轻松配置。例如，1）@hourly 时间戳等效于 0 * * * *它将在每小时的第一分钟执行一次任务。@hourly /path/to/script2）@daily 时间戳等效于 0 0 * * *它在每天的第一分钟（午夜）执行任务。它可以在执行日常工作时派上用场。@daily /path/to/script3）@weekly 时间戳等效于 0 0 * * 0它在每周的第一分钟执行 cron 任务，一周第一天是从星期日开始的。@weekly /path/to/script3）@monthly 时间戳等效于 0 0 1 * *它在每月第一天的第一分钟执行任务。@monthly /path/to/script4）@yearly 时间戳等效于 0 0 1 1 *它在每年的第一分钟执行任务，可以用于发送新年问候。@yearly /path/to/script限制 crontab作为 Linux 用户，你可以控制谁有权使用 crontab 命令。可以使用 /etc/cron.deny 和 /etc/cron.allow 文件来控制。默认情况下，只有一个 /etc/cron.deny 文件，并且不包含任何条目。要限制用户使用 crontab 实用程序，只需将用户的用户名添加到该文件中即可。当用户添加到该文件中，并且该用户尝试运行 crontab 命令时，他/她将遇到以下错误。要允许用户继续使用 crontab 实用程序，只需从 /etc/cron.deny 文件中删除用户名即可。如果存在 /etc/cron.allow 文件，则仅文件中列出的用户可以访问和使用 crontab 实用程序。如果两个文件都不存在，则只有 root 用户具有使用 crontab 命令的特权。备份 crontab 条目始终建议你备份 crontab 条目。为此，请使用语法：# crontab -l > /path/to/file.txt例如：# crontab -l > /home/james/backup.txt检查 cron 日志cron 日志存储在 /var/log/cron 文件中。要查看 cron 日志，请运行以下命令：# cat /var/log/cron要实时查看日志，请使用 tail 命令，如下所示：# tail -f /var/log/cron总结在本指南中，你学习了如何创建 cron 任务以自动执行重复性任务，如何备份和查看 cron 日志。我们希望本文提供有关 cron 作业的有用见解。请随时分享你的反馈和意见。via: https://www.linuxtechi.com/schedule-automate-tasks-linux-cron-jobs/作者：Pradeep Kumar 选题：lujun9972 译者：wxy 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出