| $ 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
}
}
}
}
|