Add something to crontab programmatically (over ssh)
my best idea so far
to check first if the content matches what should be in there and only update if it doesn't:
if [[ $(crontab -l | egrep -v "^(#|$)" | grep -q 'some_command'; echo $?) == 1 ]]
then
set -f
echo $(crontab -l ; echo '* 1 * * * some_command') | crontab -
set +f
fi
but this gets complicated enough to build a separate script around that cron task.
other ideas
you could send the string via stdin to crontab (beware, this clears out any previous crontab entries):
echo "* 1 * * * some_command" | crontab -
this should even work right through ssh:
echo "* 1 * * * some_command" | ssh user@host "crontab -"
if you want to append to the file you could use this:
# on the machine itself
echo "$(echo '* 1 * * * some_command' ; crontab -l)" | crontab -
# via ssh
echo "$(echo '* 1 * * * some_command' ; ssh user@host crontab -l)" | ssh user@host "crontab -"
For the record I'm going to suggest using /etc/cron.d/
. Only root can write files here but the entries can be configured to run as any user (without need for sudo
at run-time),
echo '0 0 * * 0 webadmin /usr/local/bin/tidy_logfiles' >/etc/cron.d/my_webadmin
An important part is that the my_webadmin
should be unique to you (not necessarily unique for the run, though) because any installation package can also write files here and you want to avoid a clash. Having this uniqueness constraint, you can update my_webadmin
with a simple overwrite, since you know it's "yours" and won't contain entries for anyone/anything else.
Furthermore, with this approach it becomes trivial to remove the cron entry
rm -f /etc/cron.d/my_webadmin
Possibly outside the scope of your question, but if you have remote access to the root account (or via sudo
) you can even provision remotely,
echo '0 0 * * 0 webadmin /usr/local/bin/tidy_logfiles' > ~/webadmin.cron
scp -p ~/webadmin.cron root@remote_host:/etc/cron.d/my_webadmin
or,
echo '0 0 * * 0 webadmin /usr/local/bin/tidy_logfiles' |
ssh -q root@remote_host 'cat >/etc/cron.d/my_webadmin'
and remove the provisioning,
ssh -nq root@remote_host rm -f /etc/cron.d/my_webadmin
(Note that in many cases you cannot provide root's password for the scp
/ssh
commands because the root account is constrained to prevent password-based logins. Instead you need to have set up public/private key certificates. Also, by implication the local account (whatever it is) will have full root access to the remote server.)
I highly recommend using Ansible* for this rather than rolling your own. Or Puppet or Chef — but Ansible is well-suited for zero-infrastructure deploy scripts like this.
That's because there are already modules meant to solve problems like this, and config management tools have have idempotence as a basic design goal — that's the property of only changing when it needs to even if you accidentally (or intentionally) run it again.
In particular, Ansible's cron module can modify user crontabs. As a bonus, if you want to later adjust to use system crontabs, it'll be a very easy tweak rather than a rewrite.
* disclaimer: I work for Red Hat, and Ansible is a Red Hat sponsored project.