$! DISK_WATCHER.COM - Watch disk usage and notify operators of alarms $! Author: Harry Flowers $! $! Normally, disks should be kept less than 75% full due to performance $! issues such as fragmentation and block allocation, and also actually $! running out of room which generally proves fatal to some processes. $! The following are parameters which you may change for monitoring disk $! space. The following ranges are recommended: $! Yellow Alerts: 80-90% Red Alerts: 85-95% Frequency: 5min-1hour $! $ YELLOW_ALERT_PERCENT = 90 ! Percent full for yellow alert $ RED_ALERT_PERCENT = 95 ! Percent full for red alert $ CHECK_FREQUENCY = "00:05:00" ! "hh:mm:ss" wait between checks $ NOTIFY_FREQUENCY = 6 ! Number of above to pass between notice $ NOTIFY_USERS = "EK3,CER,WLB,FLOWERS" $! User mailing list to notify; separate usernames with commas. Users $! will only be notified at the beginning of an alert condition. After $! that, messages will continue to be broadcast to operators, but no $! further mail messages will be sent. $! $! DISKwatcher will shut down if you create a system logical called $! DISK_WATCHER_STOP. When it discovers this logical, it will send a $! message and shut itself down. It may take up to CHECK_FREQUENCY to $! discover the logical. $! $! You may also wish to modify WITH CARE the routines RED_ALERT_ACTIONS $! and YELLOW_ALERT_ACTIONS found at the end of this command procedure. $! Typical modifications might include purging the disk drive directories $! with this command written to a command file and submitted: $! $ PURGE 'DISKNAME'[*...]*.* $! $!***************************************************************************** $ SAVERIFY = F$VERIFY(0) ! Turn off verification $ SET SYMBOL/SCOPE=NOGLOBAL ! Limit procedure to local symbols $ IF (F$MODE() .NES. "OTHER") .OR. - ! Detached is OTHER (F$GETJPI("","PRCNAM") .NES. "DISKwatcher") - ! BUT SO IS STARTUP THEN GOTO START_DETACHED ! so check proc name! $ PREVPRIV = F$SETPRV("ALTPRI,SYSPRV,SYSNAM") $ IF .NOT. F$PRIVILEGE("ALTPRI,SYSPRV,SYSNAM") THEN GOTO NO_PRIV $ ON ERROR THEN GOTO ABORTED $ RUNPRI = F$GETSYI("DEFPRI") + 1 $ IF RUNPRI .GT. 15 THEN RUNPRI = 15 $ SET PROCESS/PRIO='RUNPRI' $ REQUEST = "REQUEST/TO=(CENTRAL,DEVICES,DISKS,SECURITY)" $ ALERTFAO = "!AS Alert: !AS (!UB% full)" $ NOTIFY_USERS = F$EDIT("''NOTIFY_USERS'","TRIM") $ NOTIFY_COUNTER = 0 $ START: $ IF F$TRNLNM("DISK_WATCHER_STOP") .NES. "" THEN GOTO SHUTDOWN $ IF NOTIFY_COUNTER .GT. NOTIFY_FREQUENCY THEN NOTIFY_COUNTER = 0 $ NOTIFY_COUNTER = NOTIFY_COUNTER + 1 $ CONTEXT = "" $ ON ERROR THEN GOTO FINISHED $ LOOP: $ DISKNAME = F$DEVICE("*","DISK",,CONTEXT) - "_" $ IF DISKNAME .EQS. "" THEN GOTO FINISHED $ IF .NOT. F$GETDVI(DISKNAME,"MNT") THEN GOTO LOOP ! Not mounted $ IF F$GETDVI(DISKNAME,"FOR") THEN GOTO LOOP ! Mounted /FOR $ IF F$GETDVI(DISKNAME,"SHDW_MEMBER") THEN GOTO LOOP ! Shadowed $ IF (F$GETDVI(DISKNAME,"DEVCHAR2") .AND. 8388608) .NE. 0 THEN GOTO LOOP $ IF F$GETDVI(DISKNAME,"SWL") THEN GOTO LOOP ! Write locked $ TOTALBLOCKS = F$GETDVI(DISKNAME,"MAXBLOCK") ! Total blocks on disk $ FREEBLOCKS = F$GETDVI(DISKNAME,"FREEBLOCKS") ! Free blocks on disk $ USEDBLOCKS = TOTALBLOCKS - FREEBLOCKS ! Used blocks on disk $ PERCENTUSED = ((USEDBLOCKS*100) + (TOTALBLOCKS/2)) / TOTALBLOCKS $ DISK_ALARMED = "ALARMED_" + DISKNAME - ":" $ RED_ALERT = PERCENTUSED .GE. RED_ALERT_PERCENT $ IF RED_ALERT THEN GOTO RED_ALERT_ACTIONS $ YELLOW_ALERT = PERCENTUSED .GE. YELLOW_ALERT_PERCENT $ IF YELLOW_ALERT THEN GOTO YELLOW_ALERT_ACTIONS $ 'DISK_ALARMED' = "NONE" $ GOTO LOOP $ FINISHED: $ SET NOON $ ON ERROR THEN GOTO ABORTED $ WAIT 'CHECK_FREQUENCY' $ GOTO START $ START_DETACHED: $ PREVPRIV = F$SETPRV("DETACH,SYSPRV,ALTPRI,SYSNAM") $ IF .NOT. F$PRIVILEGE("DETACH,SYSPRV,ALTPRI,SYSNAM") THEN GOTO NO_PRIV $ WRITE SYS$OUTPUT "Starting DISKwatcher process..." $ RUN/UIC=[1,4]/INPUT='F$ENVIRONMENT("PROCEDURE")'- /OUTPUT=SYS$MANAGER:DISK_WATCHER.LOG- /PROCESS_NAME="DISKwatcher" SYS$SYSTEM:LOGINOUT.EXE $ PURGE/NOLOG/NOCONFIRM SYS$MANAGER:DISK_WATCHER.LOG $ EXIT = "EXIT" $ SET SYMBOL/SCOPE=GLOBAL $ PREVPRIV = F$SETPRV(PREVPRIV) $ SAVERIFY = F$VERIFY(SAVERIFY) $ EXIT $ NO_PRIV: $ WRITE SYS$OUTPUT - "%DISKwatcher-F-NOPRIV, DETACH, SYSPRV, ALTPRI, SYSNAM privs required." $ EXIT = "EXIT" $ SET SYMBOL/SCOPE=GLOBAL $ SAVERIFY = F$VERIFY(SAVERIFY) $ EXIT $ SHUTDOWN: $ SET NOON $ DEASSIGN/SYSTEM DISK_WATCHER_STOP $ ERRORMSG = "DISKwatcher has been requested to shut down; going offline" $ REQUEST "''ERRORMSG'" $ WRITE SYS$OUTPUT "''ERRORMSG'" $ WAIT 00:00:05 $ EXIT $ ABORTED: $ SET NOON $ ERRORMSG = "DISKwatcher has encountered an error and aborted!" $ REQUEST "''ERRORMSG'" $ IF NOTIFY_USERS .NES. "" THEN - MAIL/SUBJ="''ERRORMSG'" NL: "''NOTIFY_USERS'" $ WAIT 00:00:05 $ EXIT = "EXIT" $ SET SYMBOL/SCOPE=GLOBAL $ SAVERIFY = F$VERIFY(SAVERIFY) $ EXIT $ NOTIFY: $ ALERTSTR = F$FAO(ALERTFAO, ALARM_LEVEL, DISKNAME, PERCENTUSED) $ FIRST_ALERT = "FALSE" ! Send mail the first time the alarm sounds $ IF F$TYPE('DISK_ALARMED') .EQS. "" THEN 'DISK_ALARMED' = "NONE" $ IF 'DISK_ALARMED' .NES. ALARM_LEVEL THEN FIRST_ALERT = "TRUE" $ 'DISK_ALARMED' = ALARM_LEVEL $ IF FIRST_ALERT .OR. (NOTIFY_COUNTER .EQ. 1) THEN - REQUEST "''ALERTSTR'" ! Alert the operator consoles $ IF (NOTIFY_USERS .NES. "") .AND. FIRST_ALERT THEN - MAIL/SUBJ="DISKwatcher: ''ALERTSTR'" NL: "''NOTIFY_USERS'" $ RETURN $! $!***************************************************************************** $ RED_ALERT_ACTIONS: ! Actions to take when there has been a Red alert $ ALARM_LEVEL = "**RED**" ! Our alarm level $ GOSUB NOTIFY ! Notify operators $! Other Red Alert actions may be placed here, such as SUBMITing a purge $! command file. Don't do heavy processing here, as it will delay checks. $ GOTO LOOP ! Go check the next drive $! $ YELLOW_ALERT_ACTIONS: ! Actions to take when there has been a Yellow alert $ ALARM_LEVEL = "YELLOW" ! Our alarm level $ GOSUB NOTIFY ! Notify operators $! Other Yellow Alert actions may be placed here. See note above. $ GOTO LOOP ! Go check the next drive $!*****************************************************************************