|  | $ Save_Verify = F$Verify(0)
$goto start
$!
$!    This is a sample DCL command procedure that demonstrates how one might
$!    use the sample Data Collector code (mcc_evc_send) to 'sink' disk
$!    utilization events into a DECmcc system running the Data Collector
$!    event sink (MCC_EVC_SINK.EXE).
$!
$!    The procedure enumerates all of the disks it can find on the system and
$!    does some 'DCL arithmetic' to compute the ulilization of the disks.  
$!    Based on some (arbitrary) utilization thresholds, it will send an event
$!    of the appropriate severity to the EVC sink. 
$!
$!    Look at the comments carefully for instructions on how to customize for
$!    your particular environment.
$!
$!    NOTE: DCL arithmetic is extremely 'hack-ish' and not a very good
$!    idea for 'production' systems.   It seems to work OK for the current
$!    disk technology, but as disks get larger, this .COM is likely to
$!    break...
$!
$start:
$ on error then continue
$ on severe_error then continue
$!
$!    Change the next line to reflect the current location of mcc_evc_send.exe
$!    on your system.
$!
$ send_event :== $sys$login:mcc_evc_send.exe  
$!
$!   Change the next line to reflect the MCC system running the Data
$!   Collector Event sink that you wish to receive the event
$!
$ sink_node :== MYNODE
$!
$!   Change the next line to reflect the Data Collector on the MCC system 
$!   you wish to receive the event
$!
$ collector_name :== DISK-PROBLEMS
$!
$!   Change the next line to reflect how often you want to scan the disks
$!   (currently every hour)
$!
$ check_interval = "+01:00:00"
$!
$!    If you have any other disk controller types on your system, you will
$!    need to add it into this section so the procedure can 'find' them.
$!
$ disk_type = "DU"
$   gosub do_it
$ disk_type = "DK"
$   gosub do_it
$ disk_type = "DI"
$   gosub do_it
$!
$! Allow user to do a "one shot" for testing purposes...
$!
$ if f$edit(p1,"UPCASE") .eqs. "ONCE" then exit
$
$! Resubmit.
$!    I assume SYS$BATCH, but if you want it on a special queue, you should
$!    change the SUBMIT command below to reflect the appropriate queue.
$!
$ purge/nolog/keep=2 check_disks.log
$ submit/noprint/after="''check_interval'" 'f$environment("PROCEDURE")
$ Exit 1+0*F$Verify(Save_Verify)
$!
$do_it:
$  count = 0
$loop:
$  count = count + 1
$  in_dev  = F$DEVICE("*''disk_type'*","DISK")
$  if in_dev .nes. "" 
$  then 
$ 	IF .NOT. F$GETDVI("''in_dev'","MNT") then goto loop
$ 	max_blocks = f$getdvi("''in_dev'","MAXBLOCK")
$ 	free_blocks =  f$getdvi("''in_dev'","FREEBLOCKS")
$ 	util = 100*(max_blocks-free_blocks)/max_blocks
$       if util .ge. 80 .and. util .lt. 90 then gosub minor
$       if util .ge. 90 .and. util .lt. 95 then gosub major
$       if util .ge. 95 then gosub critical
$ 
$       goto loop
$  else 
$       return
$ endif 
$
$minor:
$ event_text == "''util'% used on disk ''IN_DEV'" + " (" + f$getdvi("''IN_DEV'","VOLNAM") + ") on ''f$trnlnm("SYS$NODE")' "
$ send_event 'sink_node "''collector_name'" -
	" " -
	"Disk Usage" -
	"''event_text'" -
	minor
$
$return
$
$major:
$ event_text == "''util'% used on disk ''IN_DEV'" + " (" + f$getdvi("''IN_DEV'","VOLNAM") + ") on ''f$trnlnm("SYS$NODE")' "
$ send_event 'sink_node "''collector_name'" -
	" " -
	"Disk Usage" -
	"''event_text'" -
	major
$
$return
$
$critical:
$ event_text == "''util'% used on disk ''IN_DEV'" + " (" + f$getdvi("''IN_DEV'","VOLNAM") + ") on ''f$trnlnm("SYS$NODE")' "
$ send_event 'sink_node "''collector_name'" -
	" " -
	"Disk Usage" -
	"''event_text'" -
	critical
$
$return
$
 | 
|  | $Save_Verify = F$Verify(0)
$goto start
$!
$!
$!
$!  This is a sample DCL procedure that demonstrates how one might use the Data
$!  Collector API and sample code to sink VMS intrusion records to a DECmcc
$!  system.
$!
$!  You will need to make modifications to some symbol definitions at the top of
$!  the file in order for this procedure to work in your environment.
$!
$!  This is supplied only as an example, with no warranties implied. ;^)
$!
$!  Please feel free to improve on my 'quick-n-dirty' DCL, as it could probably
$!  stand some "cleaning up"....
$!
$!  /doug
$!
$!
$!
$start:
$ on error then continue
$ on severe_error then continue
$!
$!    Change the next line to reflect the current location of mcc_evc_send.exe
$!    on your system.
$!
$ SEND_EVENT :== $sys$login:mcc_evc_send.exe  
$!
$!   Change the next line to reflect the MCC system running the Data
$!   Collector Event sink that you wish to receive the event
$!
$ SINK_NODE :== MYNODE
$!
$!   Change the next line to reflect the Data Collector on the MCC system 
$!   you wish to receive the event
$!
$ COLLECTOR_NAME :== SECURITY-ALERTS
$!
$!   Change the next line to reflect the Target Entity (if desired) to    
$!   're-vector' the event notfication to. (Left NULL in this case.)
$!
$ TARGET_ENTITY == " "
$!
$!   Change the next line to reflect how often you want to scan the disks
$!   (currently every 30 minutes)
$!
$ CHECK_INTERVAL = "+00:30:00"
$!
$!+--------------------------------
$
$ set noon
$ sev_threshold = 4 	! "4" indicates "Fatal" (I.e. no intrusion records found)
$ sho intru/out=sys$scratch:intrusion.log
$! 
$ stat = $status
$ sev = stat .and. 7	! sev = $severity
$ if sev .ge. sev_threshold then goto no_intruders
$
$ open/read/end=cleanup infile sys$scratch:intrusion.log
$ read/end=cleanup/err=clean_up infile line   ! get rid of header line
$read_loop:
$   read/end=cleanup/err=clean_up infile line   
$
$   intrusion = f$edit(f$extract(0,16,line),"TRIM")  !Note that this is kinda
$                                                    !dangerous, because I'm
$   type = f$edit(f$extract(16,11,line),"TRIM")      !counting spaces & am 
$                                                    !subject to the file format
$   count = f$edit(f$extract(27,7,line),"TRIM")      !changing slightly and
$                                                    !unexpectedly.
$   expiration = f$edit(f$extract(34,13,line),"TRIM")!
$                                                    !
$   source = f$edit(f$extract(47,32,line),"TRIM")    !
$						     !
$   nodename = f$trnlnm("sys$node")                  !
$                                                    !
$
$!Use an optional DEBUG argument
$!Allow the user to check that the procedure is parsing the entries correctly
$!
$   IF f$edit("''P1'","UPCASE,TRIM") .eqs. "DEBUG" 
$   THEN 
$ 	write sys$output "''intrusion'"
$ 	write sys$output "''type'"
$ 	write sys$output "''count'"
$ 	write sys$output "''expiration'"
$ 	write sys$output "''source'"
$   ENDIF
$!
$   if type .eqs. "SUSPECT" then severity = "MINOR"
$   if type .eqs. "INTRUDER" then severity = "MAJOR"
$
$   event_title = "Login failure alert: ''nodename'"
$   event_text = "''type' login alert on ''nodename' from ''source'. Intrusion: ''intrusion', Type: ''type' , Count: ''count'  Expiration: ''expiration'"
$  
$   if f$edit("''P1'","UPCASE,TRIM") .eqs. "DEBUG" then write sys$output event_text   ! just for debugging...
$
$   send_event 'sink_node  "''collector_name'" -
	"''target_entity'" -
	"''event_title'" -
	"''event_text'" -
	"''severity'"
$ 
$
$ goto read_loop ! now read in the next intrusion record...
$
$
$cleanup:	! either all done or we had a big boo boo.
$ close infile
$ delete/nolog sys$scratch:intrusion.log;*
$
$no_intruders:
$
$!
$!    I assume SYS$BATCH, but if you want it on a special queue, you should
$!    change the SUBMIT command below to reflect the appropriate queue.
$!
$ submit/noprint/log=check_intru.log/after="''check_interval'" 'f$environment("PROCEDURE")
$ purge/nolog check_intru.log ! clean up
$!
$ Exit 1+0*F$Verify(Save_Verify)
 | 
|  | Following the <FF>s are two files: a shell script (check_disks.csh) and an awk
script (chk_disk.awk) .  These may be used in together to provide the Ultrix
equivalent of the CHECK_DISKS.COM DCL  procedure I wrote.  For this script to
be run on a regular interval, you'll need to add an entry in "/usr/lib/crontab"
to run the 'check_disks.csh' script.
	Like so:
0,5,10,15,20,25,30,35,40,45,50,55 * * * * csh /usr/lib/check_disks.csh
	This will execute the script every 5 minutes, every day, forever...
What these scripts do:
----------------------
    The script 'check_disks.csh' does a 'df' of the filesystem and pipes the
    output to the awk script 'check_disks.awk'.  The awk script pulls out the
    "% used" fields of the 'df' output and uses those numbers to figure out
    whether or not to send an event.
    The awk script builds *another* file (actually a shell script) that
    contains all the "mcc_evc_send"s that need to be sent, based on the % usage
    parameters.
    When the awk script is done, control returns to the 'check_disks.csh'
    script which then executes the script created by the awk procedure, sending
    the data collector events.  Once that is done, the events script is
    deleted.
    I am *not* terribly good at U*x stuff, so if someone can improve on this
    design, then feel free to do so and post your improver version here...
/doug
#!/bin/csh
#
# File: check_disks.csh
#
df | awk -f chk_disk.awk
chmod +x events.csh
source events.csh
{record[NR] = $0}
END { 
#
# File: chk_disks.awk
#
#
# You should change the next few lines to reflect your environment...
#
# file to contain the collector script
file = "events.csh"
# ultrix host system running the script
host = "nmejg1.mcc.dec.com"     
# DECnet node to sink the events to
dest = "mcdoug"                 
# name of the Collector to use
collector = "disks"             
# Class and instance of target entity (using " " here)
target = "\" \""                
print "#!/bin/csh" >file
print "alias send /usr/mcc/mmtoolkit/examples/collection/mcc_evc_send" >file
                
        { for (i=3; i<=NR; i++)  {                 
                split(record[i], token, " ")       
                fs_node = token[1]
                total_kb = token[2]
                used_kb = token[3]
                free_kb = token[4]
                percent_used = token[5]
                mount_point = token[6]
                percent_used_num = substr(percent_used,1,index(percent_used,"%")-1)
                if (percent_used_num >95 ) severity = "Critical"
                if (percent_used_num <= 95) severity = "Major"
                if (percent_used_num <= 90) severity = "Minor"
                if (percent_used_num <= 85) severity = "Warning"
                if (percent_used_num <= 80) severity = "who_cares"
                if (severity != "who_cares") {
                        print "send", dest, collector, target, "\""percent_used " disk utilization on " fs_node "\"","\"The filesystem" , fs_node, "on host", host, "is" , percent_used , "full.\"",severity >file
                        }
                }
        }
}
 |