我定义了以下 cron 作业。
55 8 * * 3 /usr/bin/php /home/mark/dev/processes/customClient/events.php > /home/mark/dev/processes/customClient/events-`date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`.csv
0 9 * * 3 /usr/bin/echo 'The csv for last week, trying my hand at automatiging this' | /usr/bin/mutt <emailaddress> -s 'Events from `date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`' -a '/home/mark/dev/processes/customClient/events-`date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`.csv'
如果我直接从命令行运行上述命令,它似乎可以正常工作。但是,当我今天早上检查脚本的运行时,我收到一封电子邮件,说明(我解释一下,因为我不小心删除了它们)后面的勾号没有正确关闭。
答案1
与直接键入交互式 shell 中的命令相比,导致 cron 作业命令表现不同的常见原因有以下三个,大致如下:
- Cron 提供了一个有限的环境,例如,最小的
$PATH
,并且缺少其他预期变量。 - 默认情况下会调用 Cron
/bin/sh
,而您可能会交互地使用其他 shell。 - Cron 会
%
特殊对待该字符(在命令中将其转换为换行符)。 - Cron 不提供终端或图形环境。
在 crontab 文件中,您必须在所有%
字符前面加上 a \
,这会告诉 cron 在命令中只输入一个百分比。请记住,当您date
在 cron 作业中使用该命令时。
55 8 * * 3 /usr/bin/php /home/mark/dev/processes/customClient/events.php > "/home/mark/dev/processes/customClient/events-$(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d).csv"
0 9 * * 3 /usr/bin/echo 'The csv for last week, trying my hand at automatiging this' | /usr/bin/mutt <emailaddress> -s "Events from $(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d)" -a "/home/mark/dev/processes/customClient/events-$(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d).csv"
我还修复了一些引用问题:
- 除了易读性之外,这不会给您带来问题,但您不应该使用反引号进行命令替换。使用
$(…)
替代:它的解析规则更简单。 - 始终在变量和命令替换周围使用双引号:
"$somevariable"
,"$(somecommand)"
。在这里,缺少引号是无害的,因为该date
命令从未为您使用的格式返回任何特殊字符,但您必须仔细记住哪些字符是特殊字符,并在每次不加引号的替换时检查这一点。保持简单,始终使用双引号,除非您希望在结果上进行字段分割和文件名生成。 - 您有一些单引号阻止围绕某些命令替换进行扩展。请改用双引号。
答案2
我强烈建议将任何重要的 cron 作业放入它们自己的 shell 脚本文件中,原因有很多:
- 更容易调试:您只需运行脚本而不是复制粘贴一长行,并且使用正确的 shebang 行,它的行为比直接在 crontab 中使用相同的命令更可预测
- 更容易阅读:无需将其设为 200 多个字符的一行字,您可以很好地对其进行格式化,以便每个人都易于阅读和理解
- 将脚本添加到版本控制
答案3
您似乎嵌套'
在mutt
命令中:
“事件来自
date +%Y-%m-%d --date='last Wednesday'
——date +%Y-%m-%d
”
尝试使用"
而不是内部'
,以便语句读取
“事件来自
date +%Y-%m-%d --date="last Wednesday"
——date +%Y-%m-%d
”