crontab 条目中有 7 个项目意味着什么?

crontab 条目中有 7 个项目意味着什么?

一些同事建议我添加一个 cron 作业来做一些事情,但执行crontab -e并添加以下行:

 0 1 * * * . /path/to/some/file.bash

为了确保这件事正常工作,我将其更改为

 0 1 * * * . /path/to/some/file.bash && date >> /some/log

这样我就可以检查/some/log每天确实没有更多线路。

但这并没有发生。

为了调试的目的,我刚刚将这三行添加到crontab -e

 * * * * * echo "uffa" >> /home/me/without-user
 * * * * * me echo "uffa" >> /home/me/with-user
 * * * * * . echo "uffa" >> /home/me/with-any-user

我的用户名在哪里me,这导致所有三个文件都被创建,但只有第一个文件每分钟增长一行,正如您在 8 分钟后所做的检查中看到的那样:

$ for f in ~/with*; do echo ''; echo $f; cat $f; done

/home/emdeange/with-any-user

/home/emdeange/without-user
uffa
uffa
uffa
uffa
uffa
uffa
uffa
uffa

/home/emdeange/with-user

发生了什么?第二行和第三行是否使用了错误的语法,因为该行上多了一个条目?如果是这样,那么为什么还要创建该文件?


我刚刚验证了运行像这样的无意义命令确实jflkdasjflaksd > someFile会创建一个空someFile,这告诉我这两行

 * * * * * me echo "uffa" >> /home/me/with-user
 * * * * * . echo "uffa" >> /home/me/with-any-user

只是错误的,并且由于 shell 命令行处理的工作方式,文件甚至在错误发生之前就已创建。

然而,这些都是对其他人有用的线路。怎么了?

答案1

好的,首先,有两种略有不同的crontab格式。一个用于每用户 crontab,另一个用于系统 crontab(/etc/crontab以及 中的文件/etc/cron.d/)。

个人 crontab 有五个字段用于时间和日期,其余部分用于命令。系统 crontab 有五个时间和日期字段,第六个供用户运行命令,以及该命令的其余部分。如果您愿意的话,总计 6 和 7,尽管命令的最后一个“字段”的定义与其他字段有点不同。

个人 crontab 没有用户名字段,因为 crontab 隐含了所有者是谁,并且普通用户无论如何都不允许以其他人的身份运行程序。

(正如评论中所指出的,root用户的个人 crontab 也只是像任何其他用户一样的个人 crontab。它没有用户名字段,尽管root在其他方面有点特殊。所以不仅是/etc/crontab一个与你以 root 身份获得的一个crontab -e,它也有不同的格式。)


然后是..它告诉 shell 读取作为参数命名的脚本,并运行它在当前外壳中(某些 shell 称为source的别名.)。此后任何函数定义和变量分配都将可见,这与将脚本作为单独的程序运行时不同。

线路

0 1 * * * . /path/to/some/file.bash

告诉 shell(cron 启动的).../file.bash在同一个 shell 中运行。我不确定为什么他们建议这样做,而不是直接运行不带点的命令。不必初始化新的 shell 可能会有轻微的优化,但缺点是脚本必须在 cron 启动的 shell 中运行。如果 cron 启动一个普通的 sh,那么这是行不通的,但脚本是针对 zsh 的,或者是针对 Python 的。

如果该行位于全局 crontab 中,则意味着/path/to/some/file.bash以 user 身份运行.。这可能不是它的意思。

为了简单起见,我建议这样做(在使脚本可执行并添加适当的 hashbang 行(如果尚未完成)之后):

0 1 * * * /path/to/some/file.bash

然后,如果. /some/script && date >> logfile不起作用,首先要查看脚本是否因错误退出。您&&在那里使用了运算符,它告诉 shell 仅在左侧命令成功退出时才运行右侧命令。你可以. /some/script; date >> logfile无条件地运行它。或者,您. /some/script; printf "run at %s, exit status %d\n" "$(date)" "$?" >> logfile也可以尝试保存退出状态。


至于这些:

* * * * * echo "uffa" >> /home/me/without-user
* * * * * me echo "uffa" >> /home/me/with-user
* * * * * . echo "uffa" >> /home/me/with-any-user

在个人 crontab 中,第一个告诉 shell 运行echo,第二个告诉 shell 运行名为 的命令me,第三个告诉 shell 运行名为 的脚本echo。所有这些都包含重定向,并且重定向是在命令启动之前由 shell 处理的,因此在所有情况下都会创建您的文件。 (它们必须如此,因为 shell 在尝试之前无法知道该命令是否可运行,如果成功,控制权将传递给该命令,因此 shell 无法再对重定向执行任何操作。)

后面两个可能会给出错误消息,如果您的 cron 设置正确,您应该会在电子邮件中收到这些消息。


然而,这些都是对其他人有用的线路。怎么了?

如上所述,. /path/to/some/script尝试在 shell 中运行给定的脚本,对于二进制命令来说它将失败,因此. echo ...不太可能工作。0 1 * * * username echo ...可以在全局 crontab 中工作,但可能不能在个人 crontab 中工作。0 1 * * * . whatever不太可能在全球范围内工作,因为.可能不是有效的用户名。

答案2

第一行(不带用户名)是用户拥有的 crontab 的语法:

min hour dayofmonth month dayofweek command ...

第二行(带有用户名)的语法为/etc/crontab

min hour dayofmonth month dayofweek username command ...

第三行是不正确的。从技术上讲,“dot”命令从名为“echo”的文件中获取脚本,并将“uffa”设置为参数,但我怀疑你有一个脚本在名为echo.在我的系统上有一个二进制 /usr/bin/echo并尝试获取它会引发错误:

...$ LANG=C . echo
bash: .: /usr/bin/echo: cannot execute binary file

我相信如果您查看系统日志,您会看到 cron 守护程序中出现此错误消息。

相关内容