Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
Schedule::Cron(3)     User Contributed Perl Documentation    Schedule::Cron(3)

       Cron - cron-like	scheduler for Perl subroutines

	 use Schedule::Cron;

	 # Subroutines to be called
	 sub dispatcher	{
	   print "ID:	",shift,"\n";
	   print "Args:	","@_","\n";

	 sub check_links {
	   # do	something...

	 # Create new object with default dispatcher
	 my $cron = new	Schedule::Cron(\&dispatcher);

	 # Load	a crontab file

	 # Add dynamically  crontab entries
	 $cron->add_entry("3 4	* * *",ROTATE => "apache","sendmail");
	 $cron->add_entry("0 11	* * Mon-Fri",\&check_links);

	 # Run scheduler

       This module provides a simple but complete cron like scheduler.	I.e
       this module can be used for periodically	executing Perl subroutines.
       The dates and parameters	for the	subroutines to be called are specified
       with a format known as crontab entry (see "METHODS", "add_entry()" and

       The philosophy behind "Schedule::Cron" is to call subroutines
       periodically from within	one single Perl	program	instead	of letting
       "cron" trigger several (possibly	different) Perl	scripts. Everything
       under one roof.	Furthermore, "Schedule::Cron" provides mechanism to
       create crontab entries dynamically, which isn't that easy with "cron".

       "Schedule::Cron"	knows about all	extensions (well, at least all
       extensions I'm aware of,	i.e those of the so called "Vixie" cron) for
       crontab entries like ranges including 'steps', specification of month
       and days	of the week by name, or	coexistence of lists and ranges	in the
       same field.  It even supports a bit more	(like lists and	ranges with
       symbolic	names).

       $cron = new Schedule::Cron($dispatcher,[extra args])
	   Creates a new "Cron"	object.	 $dispatcher is	a reference to a
	   subroutine, which will be called by default.	 $dispatcher will be
	   invoked with	the arguments parameter	provided in the	crontab	entry
	   if no other subroutine is specified.	This can be either a single
	   argument containing the argument parameter literally	has string
	   (default behavior) or a list	of arguments when using	the "eval"
	   option described below.

	   The date specifications must	be either provided via a crontab like
	   file	or added explicitly with "add_entry()" ("add_entry").

	   extra_args can be a hash or hash reference for additional
	   arguments.  The following parameters	are recognized:

	   file	=> <crontab>
	       Load the	crontab	entries	from <crontab>

	   eval	=>  1
	       Eval the	argument parameter in a	crontab	entry before calling
	       the subroutine (instead of literally calling the	dispatcher
	       with the	argument parameter as string)

	   nofork => 1
	       Don't fork when starting	the scheduler. Instead,	the jobs are
	       executed	within current process.	In your	executed jobs, you
	       have full access	to the global variables	of your	script and
	       hence might influence other jobs	running	at a different time.
	       This behaviour is fundamentally different to the	'fork' mode,
	       where each jobs gets its	own process and	hence a	copy of	the
	       process space, independent of each other	job and	the main
	       process.	This is	due to the nature of the  "fork" system	call.

	   nostatus =>	1
	       Do not update status in $0.  Set	this if	you don't want ps to
	       reveal the internals of your application, including job
	       argument	lists.	Default	is 0 (update status).

	   skip	=> 1
	       Skip any	pending	jobs whose time	has passed. This option	is
	       only useful in combination with "nofork"	where a	job might
	       block the execution of the following jobs for quite some	time.
	       By default, any pending job is executed even if its scheduled
	       execution time has already passed. With this option set to true
	       all pending which would have been started in the	meantime are

	   catch => 1
	       Catch any exception raised by a job. This is especially useful
	       in combination with the "nofork"	option to avoid	stopping the
	       main process when a job raises an exception (dies).

	   after_job =>	\&after_sub
	       Call a subroutine after a job has been run. The first argument
	       is the return value of the dispatched job, the reminding
	       arguments are the arguments with	which the dispatched job has
	       been called.


		  my $cron = new Schedule::Cron(..., after_job => sub {
			 my ($ret,@args) = @_;
			 print "Return value: ",$ret," - job arguments:	(",join	":",@args,")\n";

	   log => \&log_sub
	       Install a logging subroutine. The given subroutine is called
	       for several events during the lifetime of a job.	This method is
	       called with two arguments: A log	level of 0 (info),1 (warning)
	       or 2 (error) depending on the importance	of the message and the
	       message itself.

	       For example, you	could use Log4perl (<>)
	       for logging purposes for	example	like in	the following code

		  use Log::Log4perl;
		  use Log::Log4perl::Level;

		  my $log_method = sub {
		     my	($level,$msg) =	@_;
		     my	$DBG_MAP = { 0 => $INFO, 1 => $WARN, 2 => $ERROR };

		     my	$logger	= Log::Log4perl->get_logger("My::Package");

		  my $cron = new Schedule::Cron(.... , log => $log_method);

	   loglevel => <-1,0,1,2>
	       Restricts logging to the	specified severity level or below.
	       Use 0 to	have all messages generated, 1 for only	warnings and
	       errors and 2 for	errors only.  Default is 0 (all	messages).  A
	       loglevel	of -1 (debug) will include job argument	lists (also in
	       $0) in the job start message logged with	a level	of 0 or	above.
	       You may have security concerns with this. Unless	you are
	       debugging, use 0	or higher. A value larger than 2 will disable
	       logging completely.

	       Although	you can	filter in your log routine, generating the
	       messages	can be expensive, for example if you pass arguments
	       pointing	to large hashes.  Specifying a loglevel	avoids
	       formatting data that your routine would discard.

	   processprefix => <name>
	       Cron::Schedule sets the process'	name (i.e. $0) to contain some
	       informative messages like when the next job executes or with
	       which arguments a job is	called.	By default, the	prefix for
	       this labels is "Schedule::Cron".	With this option you can set
	       it to something different. You can e.g. use $0 to include the
	       original	process	name.  You can inhibit this with the
	       "nostatus" option, and prevent the argument display by setting
	       "loglevel" to zero or higher.

	   sleep => \&hook
	       If specified, &hook will	be called instead of sleep(), with the
	       time to sleep in	seconds	as first argument and the
	       Schedule::Cron object as	second.	 This hook allows you to use
	       select()	instead	of sleep, so that you can handle IO, for
	       example job requests from a network connection.


		 $cron->run( { sleep =>	\&sleep_hook, nofork =>	1 } );

		 sub sleep_hook	{
		   my ($time, $cron) = @_;

		   my ($rin, $win, $ein) = ('','','');
		   my ($rout, $wout, $eout);
		   vec($rin, fileno(STDIN), 1) = 1;
		   my ($nfound,	$ttg) =	select($rout=$rin, $wout=$win, $eout=$ein, $time);
		   if ($nfound)	{
			  handle_io($rout, $wout, $eout);

	   Loads and parses the	crontab	file $file. The	entries	found in this
	   file	will be	added to the current time table	with

	   The format of the file consists of cron commands containing of
	   lines with at least 5 columns, whereas the first 5 columns specify
	   the date.  The rest of the line (i.e	columns	6 and greater)
	   contains the	argument with which the	dispatcher subroutine will be
	   called.  By default,	the dispatcher will be called with one single
	   string argument containing the rest of the line literally.
	   Alternatively, if you call this method with the optional argument
	   "eval=>1" (you must then use	the second format shown	above),	the
	   rest	of the line will be evaled before used as argument for the

	   For the format of the first 5 columns, please see "add_entry".

	   Blank lines and lines starting with a "#" will be ignored.

	   There's no way to specify another subroutine	within the crontab
	   file.  All calls will be made to the	dispatcher provided at
	   construction	time.

	   If	 you   want    to    start   up	   fresh,    you   should
	   call	"$cron->clean_timetable()" before.

	   Example of a	crontab	fiqw(le:)

	      #	The following line runs	on every Monday	at 2:34	am
	      34 2 * * Mon  "make_stats"
	      #	The next line should be	best read in with an eval=>1 argument
	      *	 * 1 1 *    { NEW_YEAR => '1',HEADACHE => 'on' }

	   Adds	a new entry to the list	of scheduled cron jobs.

	   Time	and Date specification

	   $timespec is	the specification of the scheduled time	in crontab
	   format (crontab(5)) which contains five mandatory time and date
	   fields and an optional 6th column. $timespec	can be either a	plain
	   string, which contains a whitespace separated time and date
	   specification.  Alternatively, $timespec can	be a reference to an
	   array containing the	five elements for the date fields.

	   The time and	date fields are	(taken mostly from crontab(5), "Vixie"

	      field	     values
	      =====	     ======
	      minute	     0-59
	      hour	     0-23
	      day of month   1-31
	      month	     1-12 (or as names)
	      day of week    0-7 (0 or 7 is Sunday, or as names)
	      seconds	     0-59 (optional)

	    A field may	be an asterisk (*), which always stands	for

	    Ranges of numbers are  allowed.  Ranges are	two numbers
	    separated  with  a	hyphen.	  The  specified  range	 is
	    inclusive.	 For example, 8-11  for	an  ``hours'' entry
	    specifies execution	at hours 8, 9, 10 and 11.

	    Lists  are allowed.	  A list  is a	set of	numbers	(or
	    ranges)  separated by  commas.   Examples: ``1,2,5,9'',

	    Step  values can  be used  in conjunction  with ranges.
	    Following a	range with ``/<number>'' specifies skips of
	    the	 numbers 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 in
	    the	V7 standard is ``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'', just use ``*/2''.

	    Names can also  be used for	the ``month''  and ``day of
	    week''  fields.  Use  the  first three  letters of	the
	    particular day or month (case doesn't matter).

	    Note: The day of a command's execution can be specified
		  by two fields	 -- day	of month, and  day of week.
		  If both fields are restricted	(ie, aren't *),	the
		  command will be run when either field	matches	the
		  current  time.  For  example,	``30  4	1,15  *	5''
		  would	cause a	command	to be run at 4:30 am on	the
		  1st and 15th of each month, plus every Friday


	    "8	0 * * *"	 ==> 8 minutes after midnight, every day
	    "5 11 * * Sat,Sun"	 ==> at	11:05 on each Saturday and Sunday
	    "0-59/5 * *	* *"	 ==> every five	minutes
	    "42	12 3 Feb Sat"	 ==> at	12:42 on 3rd of	February and on
				     each Saturday in February
	    "32	11 * * * 0-30/2" ==> 11:32:00, 11:32:02, ... 11:32:30 every

	   In addition,	ranges or lists	of names are allowed.

	   An optional sixth column can	be used	to specify the seconds within
	   the minute. If not present, it is implicitely set to	"0".

	   Command specification

	   The subroutine to be	executed when the the $timespec	matches	can be
	   specified in	several	ways.

	   First, if the optional "arguments" are lacking, the default
	   dispatching subroutine provided at construction time	will be	called
	   without arguments.

	   If the second parameter to this method is a reference to a
	   subroutine, this subroutine will be used instead of the dispatcher.

	   Any additional parameters will be given as arguments	to the
	   subroutine to be executed.  You can also specify a reference	to an
	   array instead of a list of parameters.

	   You can also	use a named parameter list provided as an hashref.
	   The named parameters	recognized are:

	   sub Reference to subroutine to be executed

	       Reference to array containing arguments to be use when calling
	       the subroutine

	       If true,	use the	evaled string provided with the	"arguments"
	       parameter.  The evaluation will take place immediately (not
	       when the	subroutine is going to be called)


	      $cron->add_entry("* * * *	*");
	      $cron->add_entry("* * * *	*","doit");
	      $cron->add_entry("* * * *	*",\&dispatch,"first",2,"third");
	      $cron->add_entry("* * * *	*",{'subroutine' => \&dispatch,
					    'arguments'	 => [ "first",2,"third"	]});
	      $cron->add_entry("* * * *	*",{'subroutine' => \&dispatch,
					    'arguments'	 => '[ "first",2,"third" ]',
					    'eval'	 => 1});

       @entries	= $cron->list_entries()
	   Return a list of cron entries. Each entry is	a hash reference of
	   the following form:

	     $entry = {
			time =>	$timespec,
			dispatch => $dispatcher,
			args =>	$args_ref

	   Here	$timespec is the specified time	in crontab format as provided
	   to "add_entry", $dispatcher is a reference to the dispatcher	for
	   this	entry and $args_ref is a reference to an array holding
	   additional arguments	(which can be an empty array reference). For
	   further explanation of this arguments refer to the documentation of
	   the method "add_entry".

	   The order index of each entry can be	used within "update_entry",
	   "get_entry" and "delete_entry". But be aware, when you are deleting
	   an entry, that you have to refetch the list,	since the order	will
	   have	changed.

	   Note	that these entries are returned	by value and were opbtained
	   from	the internal list by a deep copy. I.e. you are free to modify
	   it, but this	won't influence	the original entries. Instead use
	   "update_entry" if you need to modify	an exisiting crontab entry.

       $entry =	$cron->get_entry($idx)
	   Get a single	entry. $entry is either	a hashref with the possible
	   keys	"time",	"dispatch" and "args" (see "list_entries()") or	undef
	   if no entry with the	given index $idx exists.

	   Delete the entry at index $idx. Returns the deleted entry on
	   success, "undef" otherwise.

	   Updates the entry with index	$idx. $entry is	a hash ref as descibed
	   in "list_entries()" and must	contain	at least a value
	   "$entry->{time}". If	no "$entry->{dispatcher}" is given, then the
	   default dispatcher is used.	This method returns the	old entry on
	   success, "undef" otherwise.

	   This	method starts the scheduler.

	   When	called without options,	this method will never return and
	   executes the	scheduled subroutine calls as needed.

	   Alternatively, you can detach the main scheduler loop from the
	   current process (daemon mode). In this case,	the pid	of the forked
	   scheduler process will be returned.

	   The "options" parameter specifies the running mode of
	   "Schedule::Cron".  It can be	either a plain list which will be
	   interpreted as a hash or it can be a	reference to a hash. The
	   following named parameters (keys of the provided hash) are

	       If set to a true	value the scheduler process is detached	from
	       the current process (UNIX only).

	       If running in daemon mode, name the optional file, in which the
	       process id of the scheduler process should be written. By
	       default,	no PID File will be created.

	   nofork, skip, catch,	log, loglevel, nostatus, sleep
	       See "new()" for a description of	these configuration
	       parameters, which can be	provided here as well. Note, that the
	       options given here overrides those of the constructor.


	      #	Start  scheduler, detach  from current	process	and
	      #	write  the  PID	 of  the forked	 scheduler  to	the
	      #	specified file

	      #	Start scheduler	and wait forever.

	   Remove all scheduled	entries

	   Check, whether the given ID is already registered in	the timetable.
	   A ID	is the first argument in the argument parameter	of the a
	   crontab entry.

	   Returns (one	of) the	index in the  timetable	(can be	0, too)	if the
	   ID could be found or	"undef"	otherwise.


	      $cron->add_entry("* * * *	*","ROTATE");
	      defined($cron->check_entry("ROTATE")) || die "No ROTATE entry !"

	   Well, this is mostly	an internal method, but	it might be useful on
	   its own.

	   The purpose of this method is to calculate the next execution time
	   from	a specified crontab entry


	       The crontab entry as specified in "add_entry"

	       The reference time for which the	next time should be searched
	       which matches $cron_entry. By default, take the current time

	   This	method returns the number of epoch-seconds of the next matched
	   date	for $cron_entry.

	   Since I suspect, that this calculation of the next execution	time
	   might fail in some circumstances (bugs are lurking everywhere ;-)
	   an additional interactive method "bug()" is provided	for checking
	   crontab entries against your	expected output. Refer to the top-
	   level README	for additional usage information for this method.

       Daylight	saving occurs typically	twice a	year: In the first switch, one
       hour is skipped.	Any job	which which triggers in	this skipped hour will
       be fired	in the next hour. So, when the DST switch goes from 2:00 to
       3:00 a job which	is scheduled for 2:43 will be executed at 3:43.

       For the reverse backwards switch	later in the year, the behaviour is
       undefined. Two possible behaviours can occur: For jobs triggered	in
       short intervals,	where the next execution time would fire in the	extra
       hour as well, the job could be executed again or	skipped	in this	extra
       hour. Currently,	running	"Schedule::Cron" in "MET" would	skip the extra
       job, in "PST8PDT" it would execute a second time. The reason is the way
       how Time::ParseDate calculates epoch times for dates given like
       "02:50:00 2009/10/25". Should it	return the seconds since 1970 for this
       time happening 'first', or for this time	in the extra hour ? As it
       turns out, Time::ParseDate returns the epoch time of the	first
       occurence for "PST8PDT" and for "MET" it	returns	the second occurence.
       Unfortunately, there is no way to specify which entry Time::ParseDate
       should pick (until now).	Of course, after all, this is obviously	not
       Time::ParseDate's fault,	since a	simple date specification within the
       DST backswitch period is	ambigious. However, it would be	nice if	the
       parsing behaviour of Time::ParseDate would be consistent	across time
       zones (a	ticket has be raised for fixing	this). Then Schedule::Cron's
       behaviour within	a DST backward switch would be consistent as well.

       Since changing the internal algorithm which worked now for over ten
       years would be too risky	and I don't see	any simple solution for	this
       right now, it is	likely that this undefined behaviour will exist	for
       some time. Maybe	some hero is coming along and will fix this, but this
       is probably not me ;-)

       Sorry for that.

       Copyright 1999-2011 Roland Huss.

       This library is free software; you can redistribute it and/or modify it
       under the same terms as Perl itself.

       ... roland

perl v5.32.1			  2011-06-06		     Schedule::Cron(3)


Want to link to this manual page? Use this URL:

home | help