I’ve shared numerous shell scripts over the years on this blog, many of which benefit from being scheduled to run automatically on the Control Station. I’ve received emails and comments asking “How do I schedule Unix or Linux crontab jobs to run at intervals like every five minutes, every ten minutes, Every hour, etc.”? I’ll run through some specific examples next. While it’s easy enough to simply type “man crontab” from the CLI to review the syntax, it can be helpful to see specific examples.
What is cron?
Cron is a time-based job scheduler used in most Unix operating systems, including the VNX File OS (or DART). It’s used schedule jobs (either commands or shell scripts) to run periodically at fixed times, dates, or intervals. It’s primarily used to automate system maintenance, administration, and can also be used for troubleshooting.
What is crontab?
Cron is driven by a crontab (cron table) file, a configuration file that specifies shell commands to run periodically on a given schedule. The crontab files are stored where the lists of jobs and other instructions to the cron daemon are kept. Users can have their own individual crontab files and often there is a system-wide crontab file (usually in /etc or a subdirectory of /etc) that only system administrators can edit.
On the VNX, the crontab files are located at /var/spool/cron but are not intended to be edited directly, you should use the “crontab –e” command. Each NAS user has their own crontab, and commands in any given crontab will be executed as the user who owns the crontab. For example, the crontab file for nasadmin is stored as /var/spool/cron/nasadmin.
Best Practices and Requirements
First, let’s review how to edit and list crontab and some of the requirements and best practices for using it.
1. Make sure you use “crontab -e” to edit your crontab file. As a best practice you shouldn’t edit the crontab files directly. Use “crontab -l” to list your entries.
2. Blank lines and leading spaces and tabs are ignored. Lines whose first non-space character is a pound sign (#) are comments, and are ignored. Comments are not allowed on the same line as cron commands as they will be taken to be part of the command.
3. If the /etc/cron.allow file exists, then you must be listed therein in order to be allowed to use this command. If the /etc/cron.allow file does not exist but the /etc/cron.deny file does exist, then you must not be listed in the /etc/cron.deny file in order to use this command.
4. Don’t execute commands directly from within crontab, place your commands within a script file that’s called from cron. Crontab cannot accept anything on stdout, which is one of several reasons you shouldn’t put commands directly in your crontab schedule. Make sure to redirect stdout somewhere, either a log file or /dev/null. This is accomplished by adding “> /folder/log.file” or “> /dev/null” after the script path.
5. For scripts that will run under cron, make sure you either define actual paths or use fully qualified paths to all commands that you use in the script.
6. I generally add these two lines to the beginning of my scripts as a best practice for using cron on the VNX.
Descriptions of the crontab date/time fields
Commands are executed by cron when the minute, hour, and month of year fields match the current time, and when at least one of the two day fields (day of month, or day of week) match the current time.
# ┌───────────── minute (0 - 59) # │ ┌───────────── hour (0 - 23) # │ │ ┌───────────── day of month (1 - 31) # │ │ │ ┌───────────── month (1 - 12) # │ │ │ │ ┌───────────── day of week (0 - 7) # │ │ │ │ │ # │ │ │ │ │ # │ │ │ │ │ # * * * * * command to execute # 1 2 3 4 5 6 field # meaning allowed values ------- ------------ -------------- 1 minute 0-59 2 hour 0-23 3 day of month 1-31 4 month 1-12 5 day of week 0-7 (0 or 7 is Sun)
Run a command every minute
While it’s not as common to want to run a command every minute, there can be specific use cases for it. It would most likely be used when you’re in the middle of troubleshooting an issue and need data to be recorded more frequently. For example, you may want to run a command every minute to check and see if a specific process is running. To run a Unix/Linux crontab command every minute, use this syntax:
# Run “check.sh” every minute of every day * * * * * /home/nasadmin/scripts/check.sh
Run a command every hour
The syntax is similar when running a cron job every hour of every day. In my case I’ve used hourly scripts for performance monitoring, for example with the server_stats VNX script. Here’s a sample crontab entry that runs at 15 minutes past the hour, 24 hours a day.
# Brocade Backup # This command will run at 12:15, 1:15, 2:15, etc., 24 hours a day. 15 * * * * /home/nasadmin/scripts/stat_collect.sh
Run a command once a day
Here’s an example that shows how to run a command from the cron daemon once a day. In my case, I’ll usually run daily commands for report updates on our web page and for backups. As an example, I run my Brocade Zone Backup script once daily.
# Run the Brocade backup script at 7:30am 30 7 * * * /home/nasadmin/scripts/brocade.sh
Run a command every 5 minutes
There are multiple methods to run a crontab entry every five minutes. It is possible to enter a single, specific minute value multiple times, separated by commas. While this method does work, it makes the crontab list a bit harder to read and there is a shortcut that you can use.
0,5,10,15,20,25,30,35,40,45,50,55 * * * * /home/nasadmin/scripts/script.sh
The crontab “step value” syntax (using a forward slash) allows you use a crontab entry in the format sample below. It will run a command every five minutes and accomplish the same thing as the command above.
# Run this script every 5 minutes */5 * * * * /home/nasadmin/scripts/test.sh
Ranges, Lists, and Step Values
I just demonstrated the use of a step value to specify a schedule of every five minutes, but you can actually get even more granular that that using ranges and lists.
Ranges. Ranges of numbers are allowed (two numbers separated with a hyphen). The specified range is inclusive. For example, using 7-10 for an “hours” entry specifies execution at hours 7, 8, 9, & 10.
Lists. A list is a set of numbers (or ranges) separated by commas. Examples: “1,2,5,9”, “0-4,8-12”.
Step Values. Step values can be used in conjunction with ranges. Following a range with “/” specifies skips of the number’s value through the range. For example, “0-23/2” can be used in the hours field to specify command execution every other hour (the alternative being “0,2,4,6,8,10,12,14,16,18,20,22”). Steps are also permitted after an asterisk, so if you want to say “every two hours” you can use “*/2”.
While I haven’t personally used these, there is a set of built in special strings you can use, outlined below.
string meaning ------ ------- @reboot Run once, at startup. @yearly Run once a year, "0 0 1 1 *". @annually (same as @yearly) @monthly Run once a month, "0 0 1 * *". @weekly Run once a week, "0 0 * * 0". @daily Run once a day, "0 0 * * *". @midnight (same as @daily) @hourly Run once an hour, "0 * * * *".
Using a Template
Below is a template you can use in your crontab file to assist with the valid values that can be used in each column.
# Minute|Hour |Day of Month|Month |WeekDay |Command # (0-59)|(0-23)|(1-31) |(1-12)|(0-7) 0 2 12 * * test.sh
Here’s a list of the known limitations of cron and some of the issues you may encounter.
1. When cron job is run it is executed as the user that created it. Verify security requirements for the job.
2. Cron jobs do not use any files in the user’s home directory (like .cshrc or .bashrc). If you need cron to read any file that your script will need, you will need to call it from the script cron is using. This includes setting paths, sourcing files, setting environment variables, etc.
3. If your cron jobs are not running, make sure the cron daemon is running. The cron daemon can be started or stopped with the following VNX Commands (run as root):
# /sbin/service crond stop # /sbin/service crond start
4. If your job isn’t running properly you should also check the /etc/cron.allow and /etc/cron.deny files.
5. Crontab is not parsed for environmental substitutions. You can not use things like $PATH, $HOME, or ~/sbin.
6. Cron does not deal with seconds, minutes is the most granular it allows.
7. You can not use % in the command area. They will need to be escaped and if used with command substitution like the date command you can put it in backticks. Ex. `date +\%Y-\%m-\%d`. Or use bash’s command substitution $().
8. Be cautious using the day of the month and the day of week together. The day of month and day of week fields with restrictions (no *) makes this an “or” condition not an “and” condition. When either field is true it will be executed.