使用 sed 编辑 crontab

Use sed to edit crontab

我正在编写一个 sed 命令,它应该取消对 crontab 中的条目的注释。有一个更好的方法吗?想到的第一个选项是 sed。

示例:

crontab -l

# 5 * * * 3 bash test.sh

sed 命令应该取消对此项的注释。这就是我现在拥有的。

sed "s#\# 5 * * * 3 bash test.sh#5 * * * 3 bash test.sh#"

显然这个 sed 命令不能完成任务。

ps:sed 命令最终会进入脚本。

无论是使用 sed 还是其他工具都不会有太大区别。 我也会使用 sed。

但要正确修改 cron 正在使用的内容,请介意使用 crontab 命令。
不要尝试只编辑数据文件(例如 /etc/crontab 在某些系统上)。 Cron 不会接收更改!!!

您可能会使用管道:

crontab -l | sed -e "s#\# 5 \* \* \* 3 bash test.sh#5 * * * 3 bash test.sh#"| crontab 

执行更改。

然而,将 enabling/disabling 的功能添加到 运行 的脚本中不是更简单吗?

Sed 非常适合匹配特定的正则表达式和以特定方式操作文本,但在我看来这不是其中之一。虽然您可以使用 sed 来完成这项任务,但结果可能过于复杂和脆弱。

您的初始尝试是:

sed "s#\# 5 * * * 3 bash test.sh#5 * * * 3 bash test.sh#"

这会失败,因为 * 字符是正则表达式中的一个特殊字符,并被翻译为 "zero or more of the previous atom"(在本例中为 space)。严格来说,您可以通过转义正则表达式中的星号(在您的替换模式中不需要)来让这个 sed 脚本工作。

但这只对这种特定模式有帮助。如果您的一位同事决定 运行 在整点后 6 分钟而不是 5 分钟执行此脚本,以避免与其他脚本发生冲突怎么办?或者在注释符后面有一个space?突然你的 sed 替换失败了。

要取消注释掉 每个 个有问题的脚本,您可以使用:

crontab -l | sed '/# *\([^ ][^ ]*  *\)\{5\}[^ ]*test\.sh/s/^# *//' | crontab -

如果您使用的是 more modern sed,您可以将此 BRE 替换为稍短的 ERE:

crontab -l | sed -E '/# *([^ ]+  *){5}[^ ]*test\.sh/s/^# *//' | crontab -

这会获取 crontab -l 的输出,这显然是您完整的 crontab,使用 sed 对其进行操作,然后使用 crontab - 根据其输出编写一个新的 crontab。 sed 脚本匹配搜索与看起来像有效的 crontab 匹配的行(以避免只提及您的脚本的实际注释),然后进行简单的替换以仅删除开头的注释字符。匹配的模式如下所示:

  • # * - 匹配后跟零个或多个 spaces
  • 的注释字符
  • ([^ ]+ +){5} - 五个非 space 字符串,后跟 spaces
  • [^ ]* - 任意数量的非 space 字符,最多为:
  • test\.sh - 你的脚本。

但是请注意,这不匹配 所有 个有效的 crontab 时间,其中可能包括 @reboot@weekly、[=23 等标签=],等等。查看 man 5 crontab 了解详情。


awk 这样的非 sed 替代方案可能是合适的。以下 awk 解决方案对我来说更有意义:

crontab -l | awk -v script="test.sh" '
  { field=6 }
  /^# / { field++ }
  index($field,script) { sub(/^#/,"") }
  1' \
| crontab -

虽然有点长,但我觉得它更容易阅读和理解。