Use sed to edit crontab

♀尐吖头ヾ 提交于 2020-11-29 08:31:08

问题


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.

Example:

crontab -l

# 5 * * * 3 bash test.sh

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#"

Obviously this sed command doesn't do the task.

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


回答1:


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.

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).

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 -

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 -

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:

  • # * - 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.

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.


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.




回答2:


Whether using sed or other tool whould not make much a difference. I'd use sed also.

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!!!.

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?



来源:https://stackoverflow.com/questions/36330484/use-sed-to-edit-crontab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!