Another take on reliable daily/weekly/monthly scripts

May 04, '02 02:20:47AM

Contributed by: sharumpe

I am sort of annoyed that Mac OS X does not reliably run the daily, weekly and monthly scripts if your machine is not 'awake' all night. Here is my solution, with no new installed software packages. This solution uses a script to check the age of the existing log files to determine if the maintenace scripts need to be run again.

STRONG WARNING: this can disable GUI logins if you aren't careful, requiring an SSH login to fix. Done right, there is no problem.

Read the rest of the article for the how-to...

[Editor's note: As with all hints here, what the following may or may not do to your system is completely your responsibility. If you don't know what you're doing in the Terminal, I would not recommend trying this hint. There are easier methods of insuring that the maintenance scripts are run on a regular basis; MacJanitor, for example, is a freeware program which runs the maintenace scripts from the GUI. This is presented here as another method for those that might prefer a more low-level solution.]

First, we'll create a LoginHook script. I chose Perl because I am familiar with it. My script lives in /var/root/AdminScripts/LoginHook, and is as follows:

#!/usr/bin/perl -T

use strict vars;
%ENV = ();

# do daily/weekly/monthly maintenance
my $NOW = time();
my $ONEDAY = 60 * 60 * 24;
my $ONEWEEK = $ONEDAY * 7;
my $ONEMONTH = $ONEDAY * 30;

my $dailyOut = '/var/log/daily.out';
my $weeklyOut = '/var/log/weekly.out';
my $monthlyOut = '/var/log/monthly.out';

# Choose the one(s) that should be run
if (
(!-e $dailyOut)
||
(
(-e $dailyOut)
&&
($NOW - (stat($dailyOut))[9] >= $ONEDAY)
)
) {
system("sh /etc/daily 2>&1 | tee $dailyOut | mail -s "`hostname` daily output" root");
}

if (
(!-e $weeklyOut)
||
(
(-e $weeklyOut)
&&
($NOW - (stat($weeklyOut))[9] >= $ONEWEEK)
)
) {
system("sh /etc/weekly 2>&1 | tee $weeklyOut | mail -s "`hostname` weekly output" root");
}

if (
(!-e $monthlyOut)
||
(
(-e $monthlyOut)
&&
($NOW - (stat($monthlyOut))[9] >= $ONEMONTH)
)
) {
system("sh /etc/monthly 2>&1 | tee $monthlyOut | mail -s "`hostname` monthly output" root");
}
Change the permissions on the file like so:
sudo chmod 750 /var/root/AdminScripts/LoginHook
This looks at the daily, weekly and monthly logs as a way to determine the last-run time for the various scripts. If the file does not exist, or if it is old enough to signify that the script has not been run recently, it will run the scripts in the same form as used in /etc/crontab.

Next, we need to tell loginwindow to run the LoginHook script whenever someone logs in. Note that this isn't necessarily the most efficient place to do this if your machine has people logging in and out all day long, but LoginHook is crafted to only run the various scripts when necessary, no matter how many times it is called.

Edit /etc/ttys to change this:
console "/System/Library/CoreServices/loginwindow.app/loginwindow"[space]
vt100 on secure window=/System/Library/CoreServices/WindowServer[space]
onoption="/usr/libexec/getty std.9600"
to this:
console "/System/Library/CoreServices/loginwindow.app/loginwindow[space]
-LoginHook /private/var/root/AdminScripts/LoginHook" vt100[space]
on secure window=/System/Library/CoreServices/WindowServer[space]
onoption="/usr/libexec/getty std.9600"
Note that these are both one-liners. Linebreaks should be removed, and replace [space] with the actual space character. Make sure to change the path to LoginHook if you put it somewhere else.

Now reboot! There is a big caveat here - if you log in and it seems to hang after you type in your password, there is probably something wrong with the LoginHook script. If you don't want to debug the script, log in via SSH, revert the console line in /etc/ttys to remove the -LoginHook flag, and reboot.

I'm not responsible for damage to your system, your mileage may vary, caveat emptor, etc.

Comments (13)


Mac OS X Hints
http://hints.macworld.com/article.php?story=20020504022047173