(for want of a better name).
Link to github repo: https://github.com/waldner/croncal.
The problem: a crontab file containing hundreds of entries which execute jobs at many different times, and we want to know what runs when, or, perhaps more interestingly, what will run when. All displayed in a calendar-like format, so we can see that on day X, job Y will run at 9:30 and job Z will run at 00:00, 06:00, 12:00 and 18:00 (for example).
Obviously, "manually" extracting this information by looking at the crontab file itself is going to be an exercise in frustration if there are more than a handful entries (and even then, depending on how they are defined, it would probably require some messing around).
We'd like to have some program that takes a time range (start and end date or start date and duration) and a crontab file to read, and automagically produces the calendar output for the given period. Example follows to better illustrate the concept.
# Sample crontab file for this example # runs at 5:00 every day 0 5 * * * job1 # runs at 00:00 every day @daily job2 # runs every 7 hours every day, between 7 and 17, that is at 07:00 and 14:00 0 7-17/7 * * * job3 # runs at 17:30 on day 10 of each month 30 17 10 * * job4
We want to see the job timeline for the time range between 2012-06-09 00:00 and 2012-06-12 00:00. So we run it thus:
$ croncal.pl -s '2012-06-09 00:00' -e '2012-06-12 00:00' -f /path/to/crontab 2012-06-09 00:00|job2 2012-06-09 05:00|job1 2012-06-09 07:00|job3 2012-06-09 14:00|job3 2012-06-10 00:00|job2 2012-06-10 05:00|job1 2012-06-10 07:00|job3 2012-06-10 14:00|job3 2012-06-10 17:30|job4 2012-06-11 00:00|job2 2012-06-11 05:00|job1 2012-06-11 07:00|job3 2012-06-11 14:00|job3
That's basically the idea of the program described in this article. Running it with -h will print a summary of the options it accepts. Output can be in icalendar format (so the timeline can be visually seen with any calendar application), plain as above, or we can just print how many jobs would run at each time. When using the plain or icalendar formats, mostly as a debugging aid, it's possible to print the job scheduling spec as was originally found in the crontab file. This is done with the -x switch, example follows:
$ croncal.pl -s '2012-06-09 00:00' -e '2012-06-12 00:00' -f /path/to/crontab -x 2012-06-09 00:00|@daily|job2 2012-06-09 05:00|0 5 * * *|job1 2012-06-09 07:00|0 7-17/7 * * *|job3 2012-06-09 14:00|0 7-17/7 * * *|job3 2012-06-10 00:00|@daily|job2 2012-06-10 05:00|0 5 * * *|job1 2012-06-10 07:00|0 7-17/7 * * *|job3 2012-06-10 14:00|0 7-17/7 * * *|job3 2012-06-10 17:30|30 17 10 * *|job4 2012-06-11 00:00|@daily|job2 2012-06-11 05:00|0 5 * * *|job1 2012-06-11 07:00|0 7-17/7 * * *|job3 2012-06-11 14:00|0 7-17/7 * * *|job3
This should help confirm that the job should indeed run at the time shown in the first column (or not: there may be bugs!). Since the program reads from standard input if an explicit filename is not specified, it's possible to output the timeline resulting from multiple crontab files, for example by doing
cat crontab1 crontab2 crontabN | croncal.pl [ options ]
Ok, semi-UUOC but I was too lazy to implement multiple -f options.
Final words of caution:
- if you run the program over a long period of time and have cron jobs that run very often, like "* * * * *" or similar, that will produce a lot of output.
- The program was written as a quick and dirty way to solve a specific need, "works for me", is not optimized and does not try to be particularly smart of flexible. It may not be exactly what you were looking for, or may not do what you want, or in the way you want. That's life. Hopefully, it may still be useful to someone.
I had to fix latency issues on a server without access to many log files.
So croncal generated the missing data from a larger crontab, and I correlated these events with events from another logfile with latency info through remote monitoring.
Helped me alot, thanks!
Consider this more demand :) Given that one user of the script already set up a repo, it doesn't seem like much effort. In fact it takes about 60 seconds. Two bugs fixed in a year is much better than no bugs fixed at all.
You're missing the point that by putting it in github, you would allow others to more easily fork it, make improvements and updates themselves, and submit pull requests back to you -- free additional development at little effort from you!
The bug reports and feature requests you say you welcome would fit perfectly into github as that's specifically what it's designed for.
Ok ok, so I've set up a repo on github, find it here:
https://github.com/waldner/croncal
Excellent, I'll remove my clone.
Thanks for this utility. It's almost perfect for me. I was actually looking for (a) a utility do what this does, but then part (b) was to find a way to analyse cron to look for scheduled mainteance/down times to perform server restarts. If anyone has modified this code or has a suggestion to format the output of this to identify when jobs are not actually running that would be great. You can probably guess our crontab is maxed out and has stuff running almost constantly. I am trying to find the needle in the haystack.
Maybe I don't understand your need, but can't you get what you need by running grep on the output of croncal to only show entries that you want to see?
A GitHub repo would be most welcome.
https://github.com/ravenx99/croncal
I created a repo a few months ago and am subscribed to this post so I am alerted to new comments.
Thanks. I'd say the fix here is rather
Or do you have some other sample input that leads to having $field undefined at the point where you added the check for definedness?
This fixes the undef warnings, too. They were caused by a @reboot line.
Yes, that's what my patch fixes, but it just prevents it from becoming undef in a single place, rather than checking a posteriori in several places.
I think this is great. Pretty much exactly what i needed. Only wish is that the >/dev/null 2>&1 stuff that typically follows the job wasn't included.
I think it depends. In most environments I've seen, "typically" commands are not followed by that stuff. "Typically", when commands executed in cron are followed by those redirections, it's a symptom that someone is trying to sweep the dust under the carpet. Redirecting everything to /dev/null is a good way to make it impossible or very difficult to detect whether the program is running correctly or not.
Commands that are executed by cron should behave correctly (that is, not output anything if there's no error), so redirection should normally not be necessary.
And anyway, if we go down that path we must implement a shell syntax parser, which is not the goal for the program. You can always postprocess the output of croncal to remove those parts yourself. Thanks.
Thank you for this script! I have been heavily modifying it to output in an XML format that I can integrate into a web application.
Today I found it wasn't parsing jobs that are specified on day 7 properly. There is code to silently convert day 7 to 0, but it never gets called.
On this line, you declare the minimum and maximum
And later in the script you first check to see if the value is between the min/max, but then, within that if statement, you do the conversion from 7 to 0.
The code in the 2nd if statement never runs due to the first check that checks to see if the value is within the allowed range. Anyway, the fix I implemented is to just change the maximum declaration to 7 instead of 6, then it actually does silently convert it and I stop getting errors from a user's invalid cron jobs scheduled for day 7.
Thanks! That is indeed a bug. I've fixed it and updated the script.
Great work, thanks for sharing!
I have used it with large crontabs coming from several servers, and found a couple of small things that I had to change on my files for this script to work. Just in case you are interested on improving it, they were:
- zeros to the left on the minute/hour columns makes those records to be ignored
- repeating expressions for hour/minute (*/N) are not recognized and those records are ignored
Regards
Nelson
The first one is indeed a bug, which is now fixed, thanks! There was another bug as well, the program wasn't checking for interval step 0 eg */0 which shouldn't occur in practice but better to be robust.
However, regarding your second issue, intervals work fine for me:
Do you have a particular input that triggers the issue?
Another crontab syntax generator is at http://www.easycron.com/generator/cronjob
Thanks, however mine is not a crontab generator.
Thank you SO MUCH for this little gem.
It helped me a LOT :)
You should create a github project for it and publish a little, because it's great!
Agreed!
Ditto. I've just deployed this to all my production Linux servers, and I'd like to know when bug fixes/enhancements are added, and github would be ideal.
Well, given the low traffic I don't know if setting up a github repo is worth the effort, also considering that in about one and a half year there have been exactly zero new features added and a whopping two bugs fixed. In other words, don't hold your breath :-)
This doesn't mean, of course, that bug reports and/or feature requests are not welcome; rather the contrary.
If there is more demand I may consider setting up a github repo. Thanks!