使用 printf 打印出 运行 Crontab 程序出现 "invalid directive" 错误之前的时间

Using printf to print out the time before running a program in Crontab giving an "invalid directive" error

我 运行 Ubuntu 21.10 正在尝试设置 crontab 任务。

我希望在任务开始之前将日期和时间打印到控制台,所有这些都记录到日志文件中。

这是我目前拥有的。

{ printf "\%(\%Y-\%m-\%d \%H:\%M:\%S)T  Started Task\n"; <run task> } >> /path/to/log/file

当我输入 printf "%(%Y-%m-%d %H:%M:%S)T Started Task\n" 时,我得到了预期的输出:

2021-10-20 15:22:03 Started Task

然而,在 crontab 中我知道你必须使用 \ 来逃避 "%"。即使在转义了所有 % 之后我还是遇到了一个错误:

/bin/sh: 1: printf: %(: invalid directive

无论如何尝试格式化 crontab,我仍然会遇到同样的错误。

如果有人知道我做错了什么,请帮助我,谢谢。

我的具体cronjob如下:

0 * * * * { printf "\%(\%Y-\%m-\%d \%H:\%M:\%S)T  Updating Certs\n"; sudo certbot renew  --post-hook "systemctl reload nginx.service postfix.service dovecot.service"; } >> /home/ubuntu/logs/certbot.log

您的 cron 使用 sh 作为 shell。您的代码(具有 T 功能的 printf)需要 bash(版本 >= 4.2)。我建议在你的 cronjob 之前在单独的行中添加它以强制 bash as shell.

SHELL=/bin/bash

cron 可能令人惊讶,因为它的工作目录不是 $HOME 并且它的默认 shell 是 /bin/sh 而不是用户 shell.

在编写 crontab 时,您必须牢记:

  • 几乎必须使用完整路径。
  • 用大括号 { } 对指令进行分组时,必须在最后一条指令的末尾放置一个分号。
  • 使用默认 /bin/shprintf 可以限制为 POSIX 功能(这意味着它不会理解 %()T 构造)。

也就是说,您可以按照以下方式利用 /bin/sh 达到您的目的:

0 * * * * { date '+\%Y-\%m-\%d \%H:\%M:\%S  Started Task'; <command>; } >> /full/path/to/log/file

一个完全不同的解决方案是更改您的 crontab 的 shell,就像 所建议的那样。