Work the Shell - Compact Code and Cron Contraptions

作者:Dave Taylor

本月,我打算再次跑题。(你知道所有企业家都有注意力缺陷多动症,对吧?)因此,对我来说,从 A 点到 B 点最快的方式是,嗯,我们刚才在说什么?

最大能力,最少代码

读者 Peter Anderson 发送了一段代码片段,它提供了一种比我在 2006 年 12 月专栏中分享的方法更简洁的方式,将非常大的字节计数转换为千字节、兆字节和吉字节。

他的问题是:“为什么要这么多额外的代码?”

他用于执行此操作的代码片段利用了 Bash shell 的内置数学功能

value=$1
((kilo=value/1024))
((mega=kilo/1024))
((giga=mega/1024))
echo $value bytes = $kilo Kb, $mega Mb and $giga Gb

Peter,你是对的。这是一种简洁地解决问题的方法,而且很明显,可以轻松地生成一个 shell 函数,例如,将字节转换为兆字节,只需一行代码即可完成。谢谢!

正如我过去所说,我写的代码并不总是世界上最简洁的,但我在本专栏中的目标是编写可维护的代码,并将原型尽快推出,并准备好尽快进行下一件事。至少可以说,这种做法与编码世界中对优雅和完美的追求并不总是兼容的!

使用 Crontab 编码

在一个管理员邮件列表中,我偶然发现了一个有趣的问题,这个问题非常适合作为本专栏的第二部分——一个简单的脚本,实际上只是一行调用,但因为它涉及 cron 工具,所以值得我们花时间讨论。

问题是:“我需要运行一个 cron 作业,该作业在每个小时的顶部查看某个目录,并删除任何超过一小时的文件。”

通常,这是功能强大的 find 命令的工作,乍一看,只需每小时调用一次正确的 find 命令即可解决。

然而,对于新手管理员来说,涉及两个巨大的步骤,可能会让人不知所措:弄清楚如何添加新的 cron 作业,以及弄清楚 find 的正确谓词以实现他们的目标。

让我们从 find 开始。当然,了解更多关于 find 的好地方是手册页 (man find),您将在其中看到 find 可以检查三个时间戳。ctime 是上次更改时间,mtime 是上次修改时间,而 atime 是上次访问时间。但是,它们都不是创建时间,因此,如果一个文件是 90 分钟前创建的,但在 8 分钟前被触摸或更改过,则这三个时间都将报告 8 分钟,而不是 90 分钟。这可能不是什么大问题,但值得认识到,这是使此管理脚本正常工作所需的非常典型的折衷方案。

为了简单起见,我实际上会将此示例更改为删除最近 60 分钟内未被访问的文件,而不必担心它们可能早多久被创建。对于此任务,我需要 ctime。

find 对于指定 60 分钟有 +x、x 和 -x 这种令人困惑的语法,它可以理解为“超过 x”、“正好 x”和“少于 x”。如果我们使用序列-ctime -60,我们将得到与我们想要的完全相反的结果;我们将得到在过去 60 分钟内更改的文件。

或者那是我们正在指定的吗?如果没有指示单位,默认时间单位实际上是天,所以 -60 实际上是在过去 60 天内更改的文件——这不是我们想要的!

要指定分钟,我们想使用 cmin 而不是 ctime(我告诉过你 find 令人困惑)。以下是它的样子

find .  -cmin +60

但是,上述内容也匹配目录;因此,我们要添加的另一个谓词是仅将结果限制为文件

-type f

(type d仅是目录,等等)。

但是,这也不是完全正确,因为我们可能要确保我们只深入一层,而不是花费大量时间遍历复杂的文件树。这是通过很少使用的 maxdepth 参数完成的,该参数描述为“如果当前文件在树中的深度小于或等于 n,则为真。” 现在,让我们把这一切放在一起

find .  -cmin +60 -type f -maxdepth 1

看看这一切是如何组合在一起的?

现在,此要求的最后一部分实际上是删除匹配的文件或文件,我必须承认,这让我有些焦虑,因为如果您在 find 命令中犯了哪怕是最轻微的错误,您最终可能会删除大量您不想删除的文件——这不好。因此,与其仅仅使用-delete,我建议您使用-print,并让它运行一天左右,并让 cron 自动将结果报告通过电子邮件发送给您。

连接到 Cron

说到这里,从 crontab 工具访问定义您希望何时运行哪些作业的数据文件的方式是 crontab 命令。以所需用户身份登录(在这种情况下可能是 root),然后键入

crontab -e

现在,您将编辑一个包含注释(以 # 开头的行)和由五个空格分隔的值组成的行,后跟一个 sh 命令的文件,如下所示

* * * * * /home/taylor/every-minute.sh

这对系统来说相当残酷。它每天每分钟都调用此脚本——对于几乎任何进程来说都可能太过分了,但它说明了 crontab 条目的基本格式。

字段的顺序是分钟、小时、月份中的日期、月份和年份中的日期。例如,要让我们的作业每小时运行一次,我们可以简单地将分钟字段设置为特定值。例如

10 * * * * /home/taylor/every-hour.sh

每小时,在小时后的十分钟,脚本都会运行。这可行。

现在,要将所有内容组合在一起,最好的选择是将 find 命令放入一个非常短的 shell 脚本中,并使用 cron 调用该脚本,而不是将命令本身放在 crontab 文件中。为什么?因为它为您提供了很大的灵活性,并且可以非常轻松地随时扩展或修改脚本。

将本专栏中的所有内容放在一起,您应该能够真正开始利用 Linux 机器的一些重复作业功能。我是 cron 的忠实粉丝,并且在我的服务器上每晚运行许多许多作业。非常值得更多地了解它,find 命令也是如此。

现在,我们刚才在说什么?

Dave Taylor 是一位拥有 26 年 UNIX 经验的资深人士,The Elm Mail System 的创建者,以及最近畅销书 Wicked Cool Shell ScriptsTeach Yourself Unix in 24 Hours 的作者,他的技术书籍共有 16 本。他的主要网站是 www.intuitive.com

加载 Disqus 评论