bash 使用 sed 编辑 crontab
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36330484/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use sed to edit crontab
提问by u530891
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.
我正在编写一个 sed 命令,该命令应该取消对 crontab 中的条目的注释。有一个更好的方法吗?想到的第一个选项是 sed。
Example:
例子:
crontab -l
# 5 * * * 3 bash test.sh
The sed command should uncomment this entry. This is what I have now.
sed 命令应该取消注释此条目。这就是我现在所拥有的。
sed "s#\# 5 * * * 3 bash test.sh#5 * * * 3 bash test.sh#"
Obviously this sed command doesn't do the task.
显然这个 sed 命令不能完成任务。
ps:the sed command will eventually make its way into a script.
ps:sed 命令最终会进入脚本。
回答by ghoti
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 非常适合匹配特定的正则表达式和以某些方式操作文本,但在我看来这不是其中之一。虽然您可以将 sed 用于此任务,但结果可能过于复杂和脆弱。
Your initial attempt was:
您最初的尝试是:
sed "s#\# 5 * * * 3 bash test.sh#5 * * * 3 bash test.sh#"
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).
这将失败,因为该*
字符是正则表达式中的特殊字符,并被翻译为“前一个原子的零个或多个”(在本例中为空格)。严格来说,您可以通过转义正则表达式中的星号(在您的替换模式中不需要)来使这个 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.
但这仅对这种特定模式有帮助。如果您的一位同事决定在整点后 6 分钟而不是 5 分钟运行此脚本,以避免与另一个脚本发生冲突,该怎么办?或者评论字符后面有一个空格?突然你的 sed 替换失败了。
To uncomment out everycommented occurrence of the script in question, you might use:
要取消注释有问题的脚本的每个注释出现,您可以使用:
crontab -l | sed '/# *\([^ ][^ ]* *\)\{5\}[^ ]*test\.sh/s/^# *//' | crontab -
If you're using a more modern sed, you could replace this BRE with a slightly shorter ERE:
如果您使用的是更现代的 sed,您可以用稍短的 ERE 替换此 BRE:
crontab -l | sed -E '/# *([^ ]+ *){5}[^ ]*test\.sh/s/^# *//' | 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:
这需要 的输出crontab -l
,这显然是您完整的 crontab,使用 sed 对其进行操作,然后使用crontab -
. sed 脚本匹配搜索与有效 crontab 匹配的行(以避免仅提及您的脚本的实际注释),然后执行简单的替换以仅删除开头的注释字符。匹配的模式如下所示:
# *
- 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.
# *
- 匹配后跟零个或多个空格的注释字符([^ ]+ +){5}
- 五个非空格字符串,后跟空格[^ ]*
- 任意数量的非空格字符,导致:test\.sh
- 你的脚本。
Note, however, that this doesn't match allvalid crontab times, which might include tags like @reboot
, @weekly
, @midnight
, etc. Check out man 5 crontab
for details.
但是请注意,这不符合所有有效的crontab次,其中可能包括像标签@reboot
,@weekly
,@midnight
等退房man 5 crontab
的细节。
A non-sed alternative like awk
might be in order. The following awk solution makes more sense to me:
一个非 sed 替代品awk
可能是合适的。以下 awk 解决方案对我更有意义:
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.
虽然它只是有点长,但我发现它更容易阅读和理解。
回答by rpy
Whether using sed or other tool whould not make much a difference. I'd use sed also.
无论是使用 sed 还是其他工具,都没有太大区别。我也会使用 sed。
But to properly modify what cron is using, please mind to use crontab
command.
Do NOT try just editing the data file (e.g. /etc/crontab
on some systems). Cron won't pick up the changes!!!.
但是要正确修改 cron 使用的内容,请注意使用crontab
命令。
不要尝试只编辑数据文件(例如/etc/crontab
在某些系统上)。Cron 不会接受更改!!!。
You might use a pipe:
您可能会使用管道:
crontab -l | sed -e "s#\# 5 \* \* \* 3 bash test.sh#5 * * * 3 bash test.sh#"| crontab
to perform the change.
执行更改。
Nevertheless, would it not just be simpler to add the functionality of enabling/disabling into the script being run?
然而,将启用/禁用功能添加到正在运行的脚本中会不会更简单?