Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Manipulating crontab

by tune (Curate)
on Jun 21, 2001 at 19:46 UTC ( [id://90422]=perlquestion: print w/replies, xml ) Need Help??

tune has asked for the wisdom of the Perl Monks concerning the following question:

Hello All,

Some years ago, I was working on a project which was a scheduler for a radio programme. Since that programme was changed its starting time from week to week, we had to create an admin page where the administrator could change the time when a script started to record the programme.
One of my collegues created the admin page, who I did not meet since then, and I still can't imagine how he managed to modify the cron table from a perl script. Do any of you mighty Monks have the wisdom of that manner?

Thanks,

--
tune

Replies are listed 'Best First'.
Re: Manipulating crontab
by ZZamboni (Curate) on Jun 21, 2001 at 20:18 UTC
    Some time ago I wrote the code below to sort my crontab file by time (see sub compare_crons for the sorting criteria). It's very crude, but it could work as a starting point for reading a crontab file in memory. Once you read it in, you can make any changes, write it to a new file, an run the crontab command on it.

    This program leaves in each element of @db an array reference containing the 5 time fields, and a text element containing the current line, together with any comments that came before it. Of course, for making any modifications, this second element would have to be split further.

    eval 'exec perl -x $0 ${1+"$@"}' # -*-perl-*- if 0; #!perl -w # Sort a crontab by time # Each entry (possibly commented) is moved as a block with all the # comment lines before it. # Diego Zamboni, March 21, 2001. Happy Spring! use strict; use vars qw($curblock $tf @fields @db); # Regex for a time field in crontab, which can be a number, sequence o +f numbers # or an asterisk $tf='(?:[*]|(?:\d+(?:-\d+)?)(?:,\d+(?:-\d+)?)*)'; while (<>) { $curblock.=$_; if (@fields=(/^\#?($tf)\s+($tf)\s+($tf)\s+($tf)\s+($tf)\s+(.*)/)) { push @db, [[@fields], $curblock]; $curblock=""; } } foreach (sort compare_crons @db) { print "$_->[1]"; warn "-----------\n" . join(" | ", @{$_->[0]})."\n"; } # compare by month, day, hour and minute. Ignore weekday sub compare_crons { my @fa=@{$a->[0]}; my @fb=@{$b->[0]}; return compare_tf($fa[3],$fb[3]) || compare_tf($fa[2],$fb[2]) || compare_tf($fa[1],$fb[1]) || compare_tf($fa[0],$fb[0]); } # Compare two cron fields. Asterisk considered as zero, otherwise # compare by the first number sub compare_tf { my ($na,$nb); $na=($_[0]=~/^(\d*)/)[0]||0; $nb=($_[1]=~/^(\d*)/)[0]||0; return ($na <=> $nb); }

    --ZZamboni

Re: Manipulating crontab
by scain (Curate) on Jun 21, 2001 at 19:56 UTC
    tune,

    As always, it depends on what you need, but I could envision a very simple script that would create a file with the appropriate cron information in it, then executes with a system call  system ("crontab",$FILE);.

    Should be pretty easy. If there is other stuff in the crontab for that user, it gets a little tricker, but it shouldn't be undoable.

    Scott

      If you wanted to get the crontab for Auser, you could do
      my $user = "Auser"; my @crontab=`crontab -l $user`
      Edit @crontab, and output it to a file, then execute the system call.
Re: Manipulating crontab
by busunsl (Vicar) on Jun 21, 2001 at 23:53 UTC
    In addition to what's been said already a bit of background information:

    You can modify the crontab-file directly, but that will not work be enough.
    You have to change the timestamp of the directory in which the crontab-file resides, because that's what crond checks.
    And that's what the crontab command does for you. It changes the crontab-file, either by replacing or by opening an editor for you, and it 'touches' the crontab-directory to inform crond to reread that file.

Re: Manipulating crontab
by malloc (Pilgrim) on Jun 21, 2001 at 19:59 UTC
    On Linux and Slowlaris, crontab is in /etc/crontab
    Take a look at it, i would suggest using perl -i to swap out the lines that you want to change. The script will have to be run as root of course. Man crontab will give you the encoding of the time info.
    Hope this helps,
    -malloc UPDATE: just read Scains's two posts, i am too used to my personal system administration to know how to do things the right way i guess :) i just couldn't think of how you could interact with crontab -e via your script. But yeah, don't use roots crontab unless absolutely necessary, thanks for the catch Scain.
      malloc,

      Why do it as root? Generally, you shouldn't be editting /etc/crontab directly; you should instead use /usr/bin/crontab to edit it, or to replace the existing cron information with a file, as I suggested above. Using /usr/bin/crontab lets the script run as the owner of the crontab information.

      Scott

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://90422]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2024-04-19 05:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found