The Perl Advent Calendar needs more articles for 2022. Submit your idea today!


cron-sequencer - show the sequence of commands that cron would run


  cron-sequencer crontab-file             # show today's events
  cron-sequencer --show tomorrow cronfile # or tomorrow's
  cron-sequencer cronfile1 cronfile2      # show events from both crontabs
  cron-sequencer --ignore 6,9,43 file     # ignore events from these lines


cron-sequencer takes one or more crontab files, and shows the sequence of commands that cron would run, with the source line and time fields that triggered the event at that timestamp. The default is to show events for today, and to show environment variables set in the crontab file.


--show period

Show events for the given period. Options are

  • today

  • yesterday

  • tomorrow

  • last week

  • this week

  • next week

  • last hour

  • this hour

  • next hour

  • (next|last) (\d*) (minutes|hours|days|weeks)

  • ISO 8601 date/time

Single days and weeks are treated as starting at midnight (inclusive) and ending at midnight (exclusive). Single hours start at the start of the current hour. The default is today

The counted forms (next 2 days, last 24 hours, etc) start or end from the current time. Truncating to the day or hour would introduce ambiguities - doing so would mean "next 2 hours" usually wouldn't show events 119 minutes in the future, or it would mean showing between 120 and 179 minutes of events. Neither choice makes sense.

For ISO 8601 date/times, the time is ignored, and the single day is shown (midnight inclusive to midnight exclusive). See --from/--to if you need more specific date/time ranges.

(For completeness and consistency, this day is provided as an alias for today, as well as aliases next day and last day, but it's probably less clear to use these. Likewise last minute etc also exist, but they seem unlikely to be useful as the results shown will rapidly change.)

Beware - because of how Unix shells split command line arguments, and how option parsing requires a single argument to be the value, for the options that have spaces you will need to escape the spaces. So you'd need to write:

  cron-sequencer --show "last week" cronfile


  cron-sequencer "--show=last 3 days" cronfile
--from epoch time or ISO 8601 date/time
--to epoch time or ISO 8601 date/time

Specify an exact range of events to show. The start time is inclusive, the end time exclusive. Values can be

positive integer

Absolute time in Unix epoch seconds (ie seconds since 1970-01-01)


Relative time offset in seconds. For from, this specifies a start time relative to midnight gone. For to this specifies an end time relative to the start time (so gives the number of seconds of crontab events to show)


A negative integer is only permitted for from, and specifies a start time before midnight gone.

ISO 8601 date/time

Hence --from +0 --to +3600 shows events from midnight until 00:59 inclusive.

Note that interpretation of the value is in this order - hence the value 19941017 will be treated as an absolute epoch time (in August 1970) rather than the date 1994-10-17, and similarly values starting + or - will be treated as offsets not dates.


Don't show environment variables in the output.


Don't group events that happen at the same time. By default, the timestamp is shown once and then all events firing at that time are grouped together, to make it clearer that they are run simultaneously. With the --no-group option, each event is treated independently and shown with its own timestamp.


Generate JSON output. This intended for machine consumption, and the plan is to keep it stable (deletion or changes subject to deprecation cycles, but be preparated for new keys to be added). Please don't parse the default text output, as this is intended to be human-readable and might have minor changes without warning.

The default JSON output is a single JSON value with the top level an array. Within this, the default is arrays grouping events that happen at the same time, with the events represented as hashes. If --no-group is used, then the inner arrays are removed, and the top level array contains the hashes directly.

If you need JSON output in structures that these options don't offer, consider piping the output of this program to a tool such as jq.

Value(s) can be provided to --json to tweak the output


Set these options on the JSON serialiser. See "pretty" in JSON::PP and "canonical" in JSON::PP for details.


Instead of serialising a single JSON value encoding an array of structures (arrays of hashes by default, hashes with --no-group) instead output that list of structures as a sequence of JSON values, with newlines between them.


Similar to split, but output application/json-seq format - each value is preceded with an ASCII record separator character and followed by a newline. See RFC 7464

split and seq are mutually exclusive.

The --json option is parsed differently from other options with arguments - to specify arguments you must use the = form - eg --json=pretty Without this special parsing you could also have written --json pretty, but that would mean either that --json would always need an argument, or that --json pretty would be an option but --json foobar would be "display foobar as JSON" -- with silent breakage if we ever wanted to introduce a --json=foobar option.

The first choice JSON serialiser is Cpanel::JSON::XS which behaves identically, but as it doesn't provide direct link targets in its documentation this document links to the relevant sections in JSON::PP.


Shows this documentation


Shows the version


These options can be specified independently for each crontab file (or group of crontab files), and can be repeated multiple times.

--ignore <line numbers>

Ignore the given line(s) in the crontab. Specify line numbers as comma-separated lists of integers or integer ranges (just like crontab time files, aside from you can't use * or skip syntax such as /2). Line numbers start at 1.

"Ignore" is the first action of the parser, so you can ignore all of

  • command entries (particularly "chatty" entries such as * * * * *)

  • setting environment variables

  • lines with syntax errors that otherwise would abort the parse

--env NAME=value

Pre-define an environment variable for this crontab file. The variable declaration won't be shown in the output if the crontab defines the variable with the same value. Without this a crontab that starts

and has 42 events to show would generate 42 lines of output, once for each command.

If you define an environment variable on that command line that isn't set in scope in the crontab file then an unset ... line is shown. This makes it clear that the event doesn't match your expected default value.

You can't declare both --env and --hide-env


Use a pair of dashes to separate options for different files on the command line. Effectively -- resets the state to no lines ignored and no environment variables defined.


  cron-sequencer cronfile1 cronfile2

Shows events from both crontab files for today, in time order, annotated with file name, line number, time specification and environment variables.

  cron-sequencer --env MAILTO=alice cron1 -- --env MAILTO=bob cron2

Shows events from both files, but will create clearer output if cron1 declares MAILTO=alice and cron2 declares MAILTO=bob

  cron-sequencer -- cron1 --env MAILTO=alice -- --env MAILTO=bob cron2

Identical output. (This is a side effect of how options are parsed first, and then filenames.)

  cron-sequencer --env MAILTO=bob cron1 cron2 -- --ignore 3-5 cron3

Shows events from the first two files assuming the both declare MAILTO=bob, along with events from cron3 except for lines 3, 4 and 5 (with all environment variables shown, unless they were declared on the ignored lines 3, 4 and 5)


Currently the code assumes that all crontabs are run with a system timezone of UTC. Similarly all display output is shown for UTC. The work systems all run in UTC, so we don't have pressing need to fix this ourselves.


This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. If you would like to contribute documentation, features, bug fixes, or anything else then please raise an issue / pull request:


Nicholas Clark -