stocked
stocked

Reputation: 3119

How do I create a crontab through a script

I need to add a cron job thru a script I run to set up a server. I am currently using Ubuntu. I can use crontab -e but that will open an editor to edit the current crontab. I want to do this programmatically.

Is it possible to do so?

Upvotes: 245

Views: 252034

Answers (17)

Doug Kasten
Doug Kasten

Reputation: 1

I found that using echo "" | crontab -u root - works for creating a blank crontab file without modifying the files directly. Then after that you can add jobs easily using the following example:

line="*/15 * * * * /local/bin/cron.sh > /var/log/cron.log 2>&1"
(crontab -u root -l; echo "$line" ) | crontab -u root -

Upvotes: 0

Magnus
Magnus

Reputation: 18810

This would insert the cron jobs listed in my-cron-jobs.txt into the crontab, while avoiding creating duplicate entries:

( (crontab -l 2>/dev/null || true; cat my-cron-jobs.txt) | sort -u) | crontab -

More specifically, sort -u sorts all entries in the crontab and removes any duplicate lines (including duplicate empty lines).

So this has the (possibly unwanted/wanted) side effect of removing any already existing duplicate lines in the crontab, and sorting the entries.

It builds upon previous answers by Faria, Joe Casadonte and this answer from the Unix & Linux Stack exchange.

Upvotes: 2

François B.
François B.

Reputation: 1174

Simply crontab -l < "your-file-path"

Upvotes: -1

Faria
Faria

Reputation: 421

Joe Casadonte's one-liner is perfect, except if you run with set -e, i.e. if your script is set to fail on error, and if there are no cronjobs yet. In that case, the one-liner will NOT create the cronjob, but will NOT stop the script. The silent failure can be very misleading.

The reason is that crontab -l returns with a 1 return code, causing the subsequent command (the echo) not to be executed... thus the cronjob is not created. But since they are executed as a subprocess (because of the parenthesis) they don't stop the script.

(Interestingly, if you run the same command again, it will work: once you have executed crontab - once, crontab -l still outputs nothing, but it doesn't return an error anymore (you don't get the no crontab for <user> message anymore). So the subsequent echo is executed and the crontab is created)

In any case, if you run with set -e, the line must be:

(crontab -l 2>/dev/null || true; echo "*/5 * * * * /path/to/job -with args") | crontab -

Upvotes: 42

saud alkhelaiwi
saud alkhelaiwi

Reputation: 1

the easiest solution is to use echo with >> and then run crontab filename ex:

 ssh $HOST "echo \"* * * * * echo hello >> /var/spool/cron/crontabs/root\"; sleep 2; crontab /var/spool/cron/crontabs/root" 

Upvotes: 0

HeyMan
HeyMan

Reputation: 1865

Another solution to add multiple scripts to crontab at once:

cat <<EOF | crontab -
* * * * * /bin/foo.sh
* * * * * /bin/gaga.sh
EOF

Upvotes: 4

Jason Stelzer
Jason Stelzer

Reputation: 362

Cron jobs usually are stored in a per-user file under /var/spool/cron

The simplest thing for you to do is probably just create a text file with the job configured, then copy it to the cron spool folder and make sure it has the right permissions (600).

Upvotes: 9

Oleksii Kyslytsyn
Oleksii Kyslytsyn

Reputation: 2426

It is an approach to incrementally add the cron job:

  ssh USER_NAME@$PRODUCT_IP nohup "echo '*/2 * * * * ping -c2 PRODUCT_NAME.com >> /var/www/html/test.html' | crontab -u USER_NAME -"

Upvotes: 3

user2845840
user2845840

Reputation: 396

As a correction to those suggesting crontab -l | crontab -: This does not work on every system. For example, I had to add a job to the root crontab on dozens of servers running an old version SUSE (don't ask why). Old SUSEs prepend comment lines to the output of crontab -l, making crontab -l | crontab - non-idempotent (Debian recognizes this problem in the crontab manpage and patched its version of Vixie Cron to change the default behaviour of crontab -l).

To edit crontabs programmatically on systems where crontab -l adds comments, you can try the following:

EDITOR=cat crontab -e > old_crontab; cat old_crontab new_job | crontab -

EDITOR=cat tells crontab to use cat as an editor (not the usual default vi), which doesn't change the file, but instead copies it to stdout. This might still fail if crontab - expects input in a format different from what crontab -e outputs. Do not try to replace the final crontab - with crontab -e - it will not work.

Upvotes: 7

Brian Smith
Brian Smith

Reputation: 1481

Here is how to modify cron a entry without directly editing the cron file (which is frowned upon).

crontab -l -u <user> | sed 's/find/replace/g' | crontab -u <user> -

If you want to remove a cron entry, use this:

crontab -l -u <user> | sed '/find/d' | crontab -u <user> -

I realize this is not what gaurav was asking for, but why not have all the solutions in one place?

Upvotes: 3

monklof
monklof

Reputation: 171

I have written a crontab deploy tool in python: https://github.com/monklof/deploycron

pip install deploycron

Install your crontab is very easy, this will merge the crontab into the system's existing crontab.

from deploycron import deploycron
deploycron(content="* * * * * echo hello > /tmp/hello")

Upvotes: 1

cledoux
cledoux

Reputation: 4947

Crontab files are simply text files and as such can be treated like any other text file. The purpose of the crontab command is to make editing crontab files safer. When edited through this command, the file is checked for errors and only saved if there are none.

crontab [path to file] can be used to specify a crontab stored in a file. Like crontab -e, this will only install the file if it is error free.

Therefore, a script can either directly write cron tab files, or write them to a temporary file and load them with the crontab [path to temp file] command. Writing directly saves having to write a temporary file, but it also avoids the safety check.

Upvotes: 25

ganesh pathak
ganesh pathak

Reputation: 229

Even more simple answer to you question would be:

echo "0 1 * * * /root/test.sh" | tee -a /var/spool/cron/root

You can setup cronjobs on remote servers as below:

#!/bin/bash
servers="srv1 srv2 srv3 srv4 srv5"
for i in $servers
  do
  echo "0 1 * * * /root/test.sh" | ssh $i " tee -a /var/spool/cron/root"
done

In Linux, the default location of the crontab file is /var/spool/cron/. Here you can find the crontab files of all users. You just need to append your cronjob entry to the respective user's file. In the above example, the root user's crontab file is getting appended with a cronjob to run /root/test.sh every day at 1 AM.

Upvotes: 22

Dennis Williamson
Dennis Williamson

Reputation: 360683

For user crontabs (including root), you can do something like:

crontab -l -u user | cat - filename | crontab -u user -

where the file named "filename" contains items to append. You could also do text manipulation using sed or another tool in place of cat. You should use the crontab command instead of directly modifying the file.

A similar operation would be:

{ crontab -l -u user; echo 'crontab spec'; } | crontab -u user -

If you are modifying or creating system crontabs, those may be manipulated as you would ordinary text files. They are stored in the /etc/cron.d, /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly directories and in the files /etc/crontab and /etc/anacrontab.

Upvotes: 73

Joe Casadonte
Joe Casadonte

Reputation: 16889

Here's a one-liner that doesn't use/require the new job to be in a file:

(crontab -l 2>/dev/null; echo "*/5 * * * * /path/to/job -with args") | crontab -

The 2>/dev/null is important so that you don't get the no crontab for username message that some *nixes produce if there are currently no crontab entries.

Upvotes: 549

IvanGoneKrazy
IvanGoneKrazy

Reputation: 655

In Ubuntu and many other distros, you can just put a file into the /etc/cron.d directory containing a single line with a valid crontab entry. No need to add a line to an existing file.

If you just need something to run daily, just put a file into /etc/cron.daily. Likewise, you can also drop files into /etc/cron.hourly, /etc/cron.monthly, and /etc/cron.weekly.

Upvotes: 44

Dirk is no longer here
Dirk is no longer here

Reputation: 368609

Well /etc/crontab just an ascii file so the simplest is to just

 echo "*/15 * * * *   root     date" >> /etc/crontab

which will add a job which will email you every 15 mins. Adjust to taste, and test via grep or other means whether the line was already added to make your script idempotent.

On Ubuntu et al, you can also drop files in /etc/cron.* which is easier to do and test for---plus you don't mess with (system) config files such as /etc/crontab.

Upvotes: 6

Related Questions