Linux定时任务

Published on 2016 - 10 - 13

I'm sure that, as you start working with scripts, there will be a situation in which you will want to run a script at a preset time, usually at a time when you're not there. The Linux system provides a couple of ways to run a script at a preselected time: the at command and the cron table. Each method uses a different technique for scheduling when and how often to run scripts. The following sections describe each of these methods.

Scheduling a Job Using the at Command

The at command allows you to specify a time when the Linux system will run a script. The at command submits a job to a queue with directions on when the shell should run the job. The at daemon, atd, runs in the background and checks the job queue for jobs to run. Most Linux distributions start this daemon automatically at boot time.

The atd daemon checks a special directory on the system (usually /var/spool/at) for jobs submitted using the at command. By default, the atd daemon checks this directory every 60 seconds. When a job is present, the atd daemon checks the time the job is set to be run. If the time matches the current time, the atd daemon runs the job.

The following sections describe how to use the at command to submit jobs to run and how to manage jobs.

The at Command Format

The basic at command format is pretty simple:

at [-f filename] time

By default, the at command submits input from STDIN to the queue. You can specify a file name used to read commands (your script file) using the -f parameter.

The time parameter specifies when you want the Linux system to run the job. You can get pretty creative with how you specify the time. The at command recognizes lots of different time formats:

  • A standard hour and minute, such as 10:15
  • An ∼A.M./∼PMindicator, such as 10:15∼P.M.
  • A specific named time, such as now, noon, midnight, or teatime (4∼P.M.)

If you specify a time that has already past, the at command runs the job at that time on the next day.

In addition to specifying the time to run the job, you can also include a specific date, using a few different date formats:

  • A standard date format, such as MMDDYY, MM/DD/YY, or DD.MM.YY
  • A text date, such as Jul 4 or Dec 25, with or without the year
  • You can also specify a time increment:
    • Now + 25 minutes
    • 10:15∼P.M. tomorrow
    • 10:15 + 7 days

When you use the at command, the job is submitted into a job queue. The job queue holds the jobs submitted by the at command for processing. There are 26 different job queues available for different priority levels. Job queues are referenced using lowercase letters, a through z.

The higher alphabetically the job queue, the lower the priority (higher nice value) the job will run under. By default, at jobs are submitted to the at job queue. If you want to run a job at a higher priority, you can specify a different queue letter using the -q parameter.

Retrieving Job Output

When the job runs on the Linux system, there's no monitor associated with the job. Instead, the Linux system uses the e-mail address of the user who submitted the job as STDOUT and STDERR. Any output destined to STDOUT or STDERR is mailed to the user via the mail system.

Here's a simple example of using the at command to schedule a job to run:

$
$ cat test5
#!/bin/bash
#
# testing the at command
#

echo This script ran at ‘date’
echo This is the end of the script >&2
$
$ date
Mon Oct 18 14:38:17 EDT 2010
$
$ at -f test5 14:39
warning: commands will be executed using /bin/sh
job 57 at Mon Oct 18 14:39:00 2010
$
$ mail
“/var/mail/user”: 1 message 1 new
>N   1 user               Mon Oct 18 14:39  15/538   Output from your job
& 1
Date: Mon, 18 Oct 2010 14:39:00 -0400
Subject: Output from your job       57
To: user@user-desktop
From: user <user@user-desktop>

This script ran at Mon Oct 18 14:39:00 EDT 2010
This is the end of the script

& exit
$ 

The at command produces a warning message, indicating what shell the system uses to run the script, /bin/sh, along with the job number assigned to the job and the time the job is scheduled to run.

When the job completes, nothing appears on the monitor, but the system generates an e-mail message. The e-mail message shows the output generated by the script. If the script doesn't produce any output, it won't generate an e-mail message, by default. You can change that by using the -m option in the at command. This generates an e-mail message, indicating the job completed, even if the script doesn't generate any output.

Listing Pending Jobs

The atq command allows you to view what jobs are pending on the system:

$
$ at -f test5 15:05
warning: commands will be executed using /bin/sh
job 58 at Mon Oct 18 15:05:00 2010
$
$ at -f test5 15:10
warning: commands will be executed using /bin/sh
job 59 at Mon Oct 18 15:10:00 2010
$
$ at -f test5 15:15
warning: commands will be executed using /bin/sh
job 60 at Mon Oct 18 15:15:00 2010
$
$ at -f test5 15:20
warning: commands will be executed using /bin/sh
job 61 at Mon Oct 18 15:20:00 2010
$$ atq
61     Mon Oct 18 15:20:00 2010 a user
58     Mon Oct 18 15:05:00 2010 a user
59     Mon Oct 18 15:10:00 2010 a user
60     Mon Oct 18 15:15:00 2010 a user
$ 

The job listing shows the job number, the date and time the system will run the job, and the job queue the job is stored in.

Removing Jobs

Once you know the information about what jobs are pending in the job queues, you can use the atrm command to remove a pending job:

$
$ atq
59     Mon Oct 18 15:10:00 2010 a user
60     Mon Oct 18 15:15:00 2010 a user
$
$ atrm 59
$
$ atq
60     Mon Oct 18 15:15:00 2010 a user
$ 

Just specify the job number you want to remove. You can only remove jobs that you submit for execution. You can't remove jobs submitted by others.

Scheduling Regular Scripts

Using the at command to schedule a script to run at a preset time is great, but what if you need that script to run at the same time every day or once a week or once a month? Instead of having to continually submit at jobs, you can use another feature of the Linux system.

The Linux system uses the cron program to allow you to schedule jobs that need to run on a regular basis. The cron program runs in the background and checks special tables, called cron tables, for jobs that are scheduled to run.

The cron Table

The cron table uses a special format for allowing you to specify when a job should be run. The format for the cron table is:

min hour dayofmonth month dayofweek command

The cron table allows you to specify entries as specific values, ranges of values (such as 1–5) or as a wildcard character (the asterisk). For example, if you want to run a command at 10:15 on every day, you would use the cron table entry of:

15 10 * * * command

The wildcard character used in the dayofmonth, month, and dayofweek fields indicates that cron will execute the command every day of every month at 10:15. To specify a command to run at 4:15 PM every Monday, you would use the following:

15 16 * * 1 command

You can specify the dayofweek entry as either a three-character text value (mon, tue, wed, thu, fri, sat, sun) or as a numeric value, with 0 being Sunday and 6 being Saturday.

Here's another example: to execute a command at 12 noon on the first day of every month, you would use the following format:

00 12 1 * * command

The dayofmonth entry specifies a date value (1–31) for the month.

The command list must specify the full pathname of the command or shell script to run. You can add any command line parameters or redirection symbols you like, as a regular command line:

15 10 * * * /home/rich/test4 > test4out

The cron program runs the script using the user account that submitted the job. Thus, you must have the proper permissions to access the command and output files specified in the command listing.

Crontab更多功能

除了数字还有几个个特殊的符号就是*/-,*代表所有的取值范围内的数字,"/"代表每的意思,"/5"表示每5个单位,"-"代表从某个数字到某个数字,","分开几个离散的数字。

基本格式

* * * * * command
分  时  日  月  周  命令
第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令

以下是这些命令的一些示例

#每月1、10、22日
45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart
#每两个小时
0 */2 * * * date
#晚上11点到早上8点之间每两个小时,早上8点
0 23-7/2,8 * * * date

很多时候,我们计划任务需要精确到秒来执行,根据以下方法,可以很容易地以秒执行任务。
以下方法将每10秒执行一次

# crontab -e

* * * * * /bin/date >>/tmp/date.txt
* * * * * sleep 10; /bin/date >>/tmp/date.txt
* * * * * sleep 20; /bin/date >>/tmp/date.txt
* * * * * sleep 30; /bin/date >>/tmp/date.txt
* * * * * sleep 40; /bin/date >>/tmp/date.txt
* * * * * sleep 50; /bin/date >>/tmp/date.txt

Building the cron Table

Each system user can have their own cron table (including the root user) for running scheduled jobs. Linux provides the crontab command for handling the cron table. To list an existing cron table, use the -l parameter:

$ crontab -l
no crontab for rich
$

By default, each user's cron table file doesn't exist. To add entries to your cron table, use the -e parameter. When you do that, the crontab command starts a text editor with the existing cron table (or an empty file if it doesn't yet exist).

cron Directories

When you create a script that has less precise execution time needs, it is easier to use one of the pre-configured cron script directories. There are four basic directories: hourly, daily, monthly, and weekly.

$
$ ls /etc/cron.*ly
/etc/cron.daily:
0anacron      aptitude             exim4-base         man-db             sysstat
apt           bsdmainutils     logrotate             popularity-contest
apport              dpkg  mlocate   standard 
/etc/cron.hourly:

/etc/cron.monthly:
0anacron

/etc/cron.weekly:
0anacron  apt-xapian-index  man-db
$

Thus, if you have a script that needs to be run one time per day, just copy the script to the daily directory and cron executes it each day.

The anacron Program

The only problem with the cron program is that it assumes that your Linux system is operational 24 hours a day, 7 days a week. Unless you're running Linux in a server environment, this may not necessarily be true.

If the Linux system is turned off at the time a job is scheduled to run in the crontable, the job won't run. The cron program doesn't retroactively run missed jobs when the system is turned back on. To resolve this issue, many Linux distributions also include the anacron program.

If anacron determines that a job has missed a scheduled running, it runs the job as soon as possible. This means that if your Linux system is turned off for a few days, when it starts back up any jobs scheduled to run during the time it was off are automatically run.

This is a feature that's often used for scripts that perform routine log maintenance. If the system is always off when the script should run, the log files would never get trimmed and could grow to undesirable sizes. With anacron, you're guaranteed that the log files will be trimmed at least each time the system is started.

The anacron program deals only with programs located in the cron directories, such as /etc/cron.monthly. It uses timestamps to determine if the jobs have been run at the proper scheduled interval. A timestamp file exists for each cron directory and is located in /var/spool/anacron:

$
$ sudo cat /var/spool/anacron.monthly
20101123
$

The anacron program has its own table (usually located at /etc/anacrontab) to check the job directories:

$
$ cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# These replace cron's entries
1 5 cron.daily nice run-parts --report /etc/cron.daily
7 10 cron.weekly nice run-parts --report /etc/cron.weekly
@monthly 15 cron.monthly nice run-parts --report /etc/cron.monthly
$

The basic format of the anacron table is slightly different from that of the cron table:

period delay identifier command

The period entry defines how often the jobs should be run, specified in days. The anacron program uses this entry to check against the jobs' timestamp file. The delay entry specifies how many minutes after the system starts the anacron program should run missed scripts. The command entry contains the run-parts program and a cron script directory name. The run-parts program is responsible for running any script in the directory passed to it.

Notice that anacron does not run the scripts located in /etc/cron.hourly. This is because the anacron program does not deal with scripts that have execution time needs of less than daily.

The identifier entry is a unique non-blank character string—for example, cron-weekly. It is used to uniquely identify the job in log messages and error e-mails.

Start at the Beginning

The last method of starting shell scripts is to have your script run automatically either as soon as the Linux system boots or whenever a user starts a new bash shell session. Starting scripts at boot time is usually reserved for special scripts that perform system functions, such as configuring a network interface or starting a server process. However, if you're a Linux system administrator, it's possible that you'll need to perform a function every time the Linux system boots, such as resetting a custom log file or starting a custom application.

The ability to run a script every time a user starts a new bash shell (even just when a specific user starts a bash shell) also can come in handy. There are times when you want to set shell features for a shell session or just ensure that a specific file has been set.

For more Information, you can read the following two blogs to learn more about How to start your scripts at Boot Time.

Reference