how to update crontab without using crontab -e - cron

I want to update my user crontab from a java program. That is, I want to load the existing cron file, delete any obsolete lines, add new lines and then save the new file.
I'm not sure how to proceed with this. The actual cron file is in /var/spool/cron (centos) but there are warnings not to modify this file. crontab -e doesn't help unless I write a custom editor to do the file swap or a complicated shell script to pipe in the new lines after deleting the old file.
So, is there a simple way to write out a cron file and then install it?

The command crontab without any options installs a crontab from stdin.
crontab -l returns the current crontab if you need to append to the old crontab.

Related

does $crontab -e eventually updates /etc/crontab?

I'm digging along CRON and scheduling.
I setup a scheduled job to fire every minute via $crontab -e + editing the file (weirdly named "/tmp/crontab.vst6TX/crontab")
My understanding is that $crontab -e opens A crontab... and that cron.d, the daemon, picks up the crontab and APPENDS the cron job within to the (systemwide) /etc/crontab. (as per comment from crontab being saved in tmp/ in debian)
I'm watching the cron job fire every minute - yet I can't see it being added to the /etc/crontab job list... why? $crontab -l does show the job...
crontab -e and crontab -l are to edit and display (respectively) the current user's crontab file (which are physically located in /var/spool/cron/crontabs). Therefore, each user can have their own separate crontab file in that directory. So when you ran crontab -e and added a cron line, you ran crontab -l as the same user presumably, and therefore saw the line you added.
/etc/crontab is a completely different file. You are correct, it is systemwide -- notice that the cron lines in that file specify a user. The same is true for files in /etc/cron.d, the cron lines in the files will specify a user.
Oh and also, the .d suffix in cron.d does not refer to daemon. Check this post out.

What step am I missing in creating a cron job?

I can't seem to run cron jobs and I can't figure out why. I'm new to this so I might be making an amateur mistake.
First, I create a script and call it 'test.sh', putting it in the /usr/local/bin folder. The script contains:
#!/bin/bash
echo "This test works!"
Next, I create a file called 'randomtest' in the /etc/cron.d folder. The file contains:
00 09 * * * root /usr/local/bin/test.sh >> /var/log/test.log
I expect the cron job to run at 9:00 AM every day, but for some reason, it doesn't. I also don't get a log file as expected. I checked the permissions on the test.sh file and it's currently set to 755, which should work.
Is there something I'm doing wrong? Am I missing a crucial element? Do I need to add my 'randomtest' file to the crontab or something?
Reload the cron daemon by using /etc/init.d/crond reload.
(Even if it's already running!)
The problem is that you're messing around with the /etc/cron.d directory rather than using the crontab command.
Unless you definitely need a cron job to run as root, just add it to your own crontab using the crontab command. You can use crontab -e to edit it, but it's better to keep your own copy of your crontab (ideally under version control) and use the crontab filename version of the command to install it. This ensure that the cron daemon will be aware of the update, and that any syntax errors will be caught. It also means you don't need to run any commands as root; avoiding root commands unless they're actually necessary is always a good idea.
Note that system crontabs (those in /etc/crontab and under the /etc/cron.d directory -- though those locations are implementation details that you ideally shouldn't have to worry about) have a different syntax than user crontabs; each line has an extra field that specifies the account under which the commans is to be run.
If you need a command to run as root, you can either update a system crontab file (carefully!), or you can set up a user crontab for the root user, using the normal crontab command as you would for any user account.

cronjob entry in crontab -e vs /etc/crontab . Which one is better?

What is the difference when I put crontab entry in crontab -e (the default location is : /var/spool/cron/username ) and in /etc/crontab? I mean crond daemon will essentially execute both cron jobs. Then why there are two different ways to schedule cronjob ? Which one preferred over the other ?
The difference is that the crontab command is the interface provided by the system for users to manipulate their crontabs. The /etc/crontab file is a special case file used to implement a system-wide crontab. /var/spool/cron/crontabs/$USER (or whatever the path happens to be) is an implementation detail.
If you can schedule jobs using the crontab command, you should do so.
Manually editing the contents of /etc/crontab (a) requires root access, and (b) is more error-prone. You can mess up your system that way.
If the jobs are to be run under your own user account, there's no need to use root access.
Even if the jobs are to run as root, it probably still makes more sense to use the crontab command invoked from the root account. (For one thing, it should detect syntax errors in the file.)
Personally, I don't use crontab -e. Instead, I have a crontab file that I keep in a source control system, and I use the crontab filename form of the command to install it. That way, if I mess something up, it's easy to revert to an earlier version.
Differences :
$PATH
(On my Red Hat 7 system)
Running via /etc/crontab : $PATH is /sbin:/bin:/usr/sbin:/usr/bin
Running via crontab -e : $PATH is /usr/bin:/bin
Access
Only root can access /etc/crontab
User can access their own /var/spool/cron/user-name
Format
/etc/crontab needs an extra parameter, preceding the command, which specifies the user.
crontab -e (/var/spool/cron/user-name) obviously does not need the user name in the crontab entry.

Script runs from terminal, but not cron. What edits to this script do I need to make?

I have a script used for zipping a database and site files, then dumps the output into a backup folder on the server. The script runs fine from the command line, but it will not work through cron.
After much research, I am thinking that cron cannot run it in its current form because it runs in a different environment.
Here is the script, saved as file_name.sh
#!/bin/bash
NOW=$(date +"%Y-%m-%d-%H%M")
FILE="website.com.$NOW.tar"
BACKUP_DIR="/backupfolder"
WWW_DIR="/var/www/website/"
DB_USER="dbuser"
DB_PASS="dbpw"
DB_NAME="dbname"
DB_FILE="website.com.$NOW.sql"
WWW_TRANSFORM='s,^var/www/website,www,'
DB_TRANSFORM='s,^backupfolder,database,'
tar -cvf $BACKUP_DIR/$FILE --transform $WWW_TRANSFORM $WWW_DIR
mysqldump -u$DB_USER -p$DB_PASS $DB_NAME > $BACKUP_DIR/$DB_FILE
tar --append --file=$BACKUP_DIR/$FILE --transform $DB_TRANSFORM $BACKUP_DIR/$DB_FILE
rm $BACKUP_DIR/$DB_FILE
gzip -9 $BACKUP_DIR/$FILE
I currently have the script stored in /usr/local/scripts/
Is there something wrong with the above code that does not allow it to run through cron?
Which crontab should it go in? crontab -e from terminal, or /etc/crontab? They are two different files.
Several things come to mind: first, one of the most common problems with cron jobs is that generally crond runs things with a very minimal PATH (usually just /usr/bin:/bin), so if the script uses any commands from some other binaries directory, it'll fail. Where is mysqldump on your system (run which mysqldump if you aren't sure)? If this is the problem, adding PATH=/usr/local/bin:/usr/bin:/bin (or whatever's appropriate in your case) at the beginning of your script should fix it. Alternately, you can set PATH in the crontab file (put this line before the entry that runs your script).
If that's not the problem, my next step would be to capture the script's output, with something like:
1 1 * * * /usr/local/scripts/file_name.sh >/tmp/file_name.log 2>&1
... and see if the output is informative. BTW, as #tripleee mentioned, the format of your cron entry is suitable for the files crontab -e edits, but not for /etc/crontab. The /etc version has an additional field specifying which user to run the job as, e.g.
1 1 * * * eric /usr/local/scripts/file_name.sh >/tmp/file_name.log 2>&1
Best practice is to always use crontab -e (the resultant files are usually in /var/spool/cron/) and this works on every unix and linux platform I ever worked on.
Other common issues with cron execution are missing environment variables. Any environment variables set in .bash_profile (or .profile if you use korn shell) will not necessarily be present in the cron environment. This can be overcome by including them in your script.
As Gordon said, paths are another suspect. You can always full path you executables in your script (eg /bin/mysqldump). Some of the more cynical of us do this anyway to make sure we are executing what we intended as apposed to some other file of the same name in the current path.
I can only guess at your specific problem since you fixed it by creating /scripts, that perhaps the permissions on /usr/local/scripts directory did not allow execution by the cron user?
I have had to remove the extension (.sh) for cron to run in some instances.
So I fixed it. Not sure what the problem was, but this worked for me.
I originally had the scripts located in /usr/local/scripts/
I created a new directory here - /scripts/ and moved the scripts there. The new crontab -e command looked like this:
1 1 * * * bash /scripts/file_name.sh
Works perfectly. Again, I am not sure what the issue was before, but it works now.

Crontab for script

My script is under /u01/software/aditya/script/ directory. Name of script is myscript.sh. I am able to run this script and getting output too. I am trying to set a cronjob for this script at 6.30 daily morning. I am doing this as root user. I have done following steps but not getting output.
crontab -e
30 06 * * * sh /u01/software/aditya/script/myscript.sh >> /u01/software/aditya/hello.log
:wq
but not getting any update in hello.log file :( . please help….
First check your cron log file which is usually in /var/log/syslog. There should be entries similar to
Sep 17 06:30:01 localhost CRON[17725]: (root) CMD (sh /u01/software/aditya/script/myscript.sh >> /u01/software/aditya/hello.log)
If not, your script has never been run. This could be due to a broken crontab file. You should make sure that this file always ends with a newline, better insert more than one at the end so that deleting one accidentally won't break the file.
If this line exists in the log file then your script has been run, but didn't generate any output. This can happen due to a different environment when being run via cron.
Also note that >> only redirects stdout, not stderr. If you want to redirect stderr too, then add 2>&1 at the end of the line.
Normally this is caused by a PATH problem. There is a very good chance that myscript.sh calls a command that is not available in the PATH that cron runs with. Some options to fix this are:
Make sure that every command in myscript.sh is a full path-reference (tedious)
Add source ~/.bashrc to the top of myscript.sh
Add export PATH=$PATH:<colon delimited list of paths necessary for myscript.sh to run correctly>
Pick one of the above, or you could also choose one of the options here: Hourly cron job did not run

Resources