Updating CRON with bash script

2020-07-10 20:28发布

问题:

Can anyone see my syntax error here? Trying to edit/update a cron job, but the file is not being updated.

crontab -l | sed 's%*/5 * * * * cd /home/administrator/anm-1.5.0 && ./anm.sh%*/10 * * * * cd /home/administrator/anm-1.5.0 && ./anm.sh%' | crontab -

* UPDATE *

So im still having trouble with this. Ultimately I am trying to pull a value from a config file $FREQ (minutes) to run the job. The script will first check to see if the value in the config is different than the value currently in the crontab. If the value is different, it will update the crontab with the new value. The crontab (both initial install and updates) also pulls the running directory and script name from variables. Example:

DIR=`pwd`
SCRIPT=`basename $0`
CRONTMP=`crontab -l | grep anm.sh`
crontab -l | sed 's%'$CTMP'%*/'$FREQ' * * * * cd '$DIR' && ./'$SCRIPT'%' | crontab -

Something along those lines. Obviously this is missing a few things, but that should give you the general idea.

Thanks for the help!

* UPDATE *

Ok so things are moving along, but I am still having one tiny problem. I think I have most of the logic worked out. Here is the entire (pertinent) part of the script so you can get a feel for exactly what I am trying to accomplish.

Remember: $SCRIPT and $DIR are defined outside the function and are just equal to the scripts name (anm.sh for example), and the current working directory. And I took your suggestion and updated all my code. I now use SCRIPT=$(basename $0). Thanks

function CRON {
  if [ "`crontab -l | grep $SCRIPT`" \> " " ]; then
    CTMP=$(crontab -l | grep $SCRIPT)
    if [ "$CTMP" = "*/$FREQ * * * * cd $DIR && ./$SCRIPT" ]; then
      echo "$GREEN No modifications detected $RESET"
    else
      crontab -l | "sed s%$CTMP%*/$FREQ * * * * cd $DIR && ./$SCRIPT%" | crontab -
    fi
  else
    echo "$YELLOW CRON not detected - Installing defaults $RESET"
    (crontab -l ; echo "*/$FREQ * * * * cd $DIR && ./$SCRIPT") | crontab -
  fi
}

Essentially, when the function runs, it first checks to see if the cron job is even installed (perhaps this is the first time the script has run). If it doesn't detect anything, it appends the cron job to the crontab file. This works great so far. Next, if the function does detect that the cron job has been installed, it compares it vs the frequency (in minutes) set in the configuration file. If they are the same, no modification has been made to the config file and the script moves on. Lastly, if the values are indeed different, it then tries to update the corresponding line in the crontab file to reflect the changes made in the configuration file. This last part fails. Currently its just overwriting the crontab file completely to blank.

* UPDATE *

It looks like there is a major issue with the following line. This is not properly pulling the desired line out of the crontab and storing it to the variable CTMP:

CTMP=$(crontab -l | grep $SCRIPT)

when I echo out CTMP, I get a bunch of unexpected results. Apparently I am using grep incorrectly here.

Ok this issue was resolved. The variable was being stored correctly, I was just echoing it out incorrectly.

* UPDATE 06/24/13 5:08am *

The last issue seems to be the sed line. Here is the error message I am researching now.

sed s%*/12 * * * * cd /home/administrator/anm-1.5.0 && ./anm.sh%*/10 * * * * cd /home/administrator/anm-1.5.0 && ./anm.sh%: No such file or directory

It looks like it's trying to replace the line, but failing.

* UPDATE 06/24/13 5:45am *

So the error message above was ofcourse caused by my own stupidity. I was including sed inside the quotes. I have since removed the command from the quotes, however the issue still persists. I have tried single quotes, double quotes, escaping * and . with no luck. The cron file is still not updating. Here is the current code:

function CRON {
  if [ "`crontab -l | grep $SCRIPT`" \> " " ]; then
    CTMP="$(set -f; crontab -l | grep $SCRIPT)"
    if [ "$CTMP" = "*/$FREQ * * * * cd $DIR && ./$SCRIPT" ]; then
      echo "$GREEN No modifications detected $RESET"
    else
      crontab -l | sed "s%$CTMP%*/$FREQ * * * * cd $DIR && ./$SCRIPT%" | crontab -
    fi
  else
    echo "$YELLOW CRON not detected - Installing defaults $RESET"
    (crontab -l ; echo "*/$FREQ * * * * cd $DIR && ./$SCRIPT") | crontab -
  fi
}

* UPDATE 06/24/13 6:05am *

Perhaps the issue is I'm not escaping everything. ie, the variables inside the sed expression once expanded have characters that need escaping? Could that be the issue? If so, im not exactly sure how to resolve this. Please help.

* SOLVED *

I did indeed have to escape the variables as well before passing them to sed. Here is the code:

CTMPESC=$(sed 's/[\*\.&]/\\&/g' <<<"$CTMP")
DIRESC=$(sed 's/[\*\.&]/\\&/g' <<<"$DIR")
SCRIPTESC=$(sed 's/[\*\.&]/\\&/g' <<<"$SCRIPT")
crontab -l | sed "s%$CTMPESC%\*/$FREQ \* \* \* \* cd $DIRESC \&\& \./$SCRIPTESC%" | crontab -

回答1:

Try escaping the * and . in your substitution portion.

crontab -l | sed 's%\*/5 \* \* \* \* cd /home/administrator/anm-1\.5\.0 && \./anm\.sh%*/10 * * * * cd /home/administrator/anm-1.5.0 && ./anm.sh%' | crontab -

or, you can put in a regex that matches your job and just change the timing

crontab -l | sed '/anm\.sh/s,^\*/5,*/10,' | crontab -


回答2:

* SOLVED *

I did indeed have to escape the variables as well before passing them to sed. Here is the code:

CTMPESC=$(sed 's/[\*\.&]/\\&/g' <<<"$CTMP")
DIRESC=$(sed 's/[\*\.&]/\\&/g' <<<"$DIR")
SCRIPTESC=$(sed 's/[\*\.&]/\\&/g' <<<"$SCRIPT")
crontab -l | sed "s%$CTMPESC%\*/$FREQ \* \* \* \* cd $DIRESC \&\& \./$SCRIPTESC%" | crontab -


回答3:

I would offer this shorter version:

crontab -l | sed '/cd /s#\/5#\/10#' | crontab -

which should change 5 to 10 where the line has cd. Or use anm.sh in place of cd as an address to be more specific in case there is more than one cd line:

crontab -l | sed '/anm\.sh/s#\/5#\/10#' | crontab -