使用sed编辑crontab [英] Use sed to edit crontab

查看:72
本文介绍了使用sed编辑crontab的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a sed command that should uncomment an entry in crontab. Is there a better way to do this? The first option that comes to mind is sed.

示例:

crontab -l

# 5 * * * 3 bash test.sh

sed命令应取消注释该条目.这就是我现在所拥有的.

The sed command should uncomment this entry. This is what I have now.

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

很明显,这个sed命令不会执行任务.

Obviously this sed command doesn't do the task.

ps:sed命令最终将进入脚本.

ps:the sed command will eventually make its way into a script.

推荐答案

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

Sed is great for matching specific regular expressions and manipulating text in certain ways, but this doesn't seem to me to be one of them. While you can use sed for this task, the result is perhaps overly complex and fragile.

您最初的尝试是:

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

此操作失败,因为 * 字符是正则表达式中的特殊字符,并且被转换为零个或多个前一个原子"(在这种情况下为空格).严格来说,您可以通过转义正则表达式中的星号来使此sed脚本起作用(替换模式中不需要).

This fails because the * character is a special character within your regular expression, and is translated as "zero or more of the previous atom" (in this case, a space). Strictly speaking, you may get this sed script to work by escaping the asterisks in your regex (not required in your replacement pattern).

但这仅适用于此特定模式.如果您的一个同事决定在小时后的6分钟而不是5分钟后运行此脚本,以避免与另一个脚本发生冲突,该怎么办?还是在注释字符后面有空格?突然,您的sed替换失败.

But this only helps for this specific pattern. What if one of your co-workers decides to run this script at 6 minutes after the hour instead of 5, in order to avoid conflict with another script? Or there's a space after the comment character? Suddenly your sed substitution fails.

要取消注释每个出现的脚本的 评论,可以使用:

To uncomment out every commented occurrence of the script in question, you might use:

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

如果您使用的是更现代的sed ,则可以用稍短的ERE代替此BRE:

If you're using a more modern sed, you could replace this BRE with a slightly shorter ERE:

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

这将使用 crontab -l <​​/code>的输出,这显然是您完整的crontab,使用sed对其进行操作,然后使用 crontab-.sed脚本匹配搜索匹配看起来像有效crontab的行(以避免实际的注释只提及您的脚本),然后进行简单替换以在开始时仅删除注释字符.匹配的模式会像这样爆发:

This takes the output of crontab -l, which is obviously your complete crontab, manipulates it with sed, and then writes a new crontab based on its output using crontab -. The sed script matches searches for lines matching what looks like a valid crontab (to avoid actual comments that simply mention your script), then does a simple substitution to remove only the comment character at the start. The matched pattern breaks out like this:

  • #* -匹配注释字符,后跟零个或多个空格
  • ([[^] + +){5} -五个非空格字符串,后跟空格
  • [^] * -任意数量的非空格字符,导致:
  • test \ .sh -您的脚本.
  • # * - Matches the comment character followed by zero or more spaces
  • ([^ ]+ +){5} - five non-space strings, followed by spaces
  • [^ ]* - Any number of non-space characters, which lead up to:
  • test\.sh - your script.

但是请注意,这与所有有效的crontab时间都不匹配,其中可能包含 @reboot @weekly @midnight 等.请查看 man 5 crontab 了解详细信息.

Note, however, that this doesn't match all valid crontab times, which might include tags like @reboot, @weekly, @midnight, etc. Check out man 5 crontab for details.

可能会按顺序排列诸如 awk 之类的非sed选项.以下awk解决方案对我来说更有意义:

A non-sed alternative like awk might be in order. The following awk solution makes more sense to me:

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

虽然稍长一点,但我发现它更易于阅读和理解.

While it's just a little longer, I find it easier to read and understand.

这篇关于使用sed编辑crontab的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆