//=============================================================================
//
// Task: WEBFSMON.TSK
// (Generates an .HTML page with Server Status information/graphs)
// Author: Avanti Technology, Inc.
// http://www.avanti-tech.com
// Version: 1.03 - Updated Release (13 Mar 2009) - Fix for v4.20 issue
// 1.02 - Updated Release (04 Apr 2008) - NW v6.5 SP7
// 1.01 - Updated Release (15 Mar 2005)
//
// Description:
// ============
// Generates an .HTML page showing the Server Status information with
// simple graphs, automatically updated every minute, for any NetWare
// v5.0 (or later) Server (does not require WEB Server software or IP).
// The task runs continuously, updating the WEBFSMON.HTML Page every
// minute, until the task is terminated or TaskMaster is unloaded.
// Percentage statistics (i.e., CPU Utilization, Cache Buffers, etc.
// with ranges of 0-100%) are graphed in Green (0-50%), Yellow (51-89%),
// and Red (90-100%). Volume Space is graphed similarly with Green used
// for Free Space, Yellow for Purgeable Space, and Red for Used Space.
//
// This use of colors is intended to provide quick information at a glance.
//
// The WEBFSMON.HTML file can be directed to any directory on the Server,
// including the SYS:LOGIN directory, thus allowing general access to
// Server Status information by any network user able to attach to the
// Server (no Login required). For Servers with WEB Server software
// loaded or with directories accessible via generic IP means, the
// file can be directed to any directory that allows sufficient access.
//
// Objective:
// ==========
// Provide general access to generic Server Status information without
// concerns for security or account management.
//
// Usage:
// ======
// Script can be manually executed using the TaskMaster TMRUN command
// at the TMConsole (Shell) Screen:
//
// Example: TMRUN [vol:path\]WEBFSMON.TSK
//
// Note: [vol:path\] is not required if the task resides either
// in SYS:SYSTEM or the TaskMaster NLM load directory.
//
// Script can be scheduled for automatic execution using Client interface or
// using the TaskMaster TMSCHEDULE command at the TMConsole (Shell) Screen:
//
// Examples: TMSCHEDULE ADD WEBFSMON.TSK 01 02:00
// (Executes the 1st of each month at 2:00am)
//
// TMSCHEDULE ADD WEBFSMON.TSK YNNNNNN 02:00
// (Executes every Sunday [SMTWTFS] at 2:00am)
//
// Note: Scheduled tasks must reside either in SYS:SYSTEM or the
// TaskMaster NLM load directory for security reasons.
//
// Note: Logic has been incorporated to avoid multiple concurrent executions.
// Therefore, it can be scheduled as frequently as desired to insure
// continuous operation.
//
// Compatibility:
// ==============
// This task has been tested on the following platforms without demonstrating
// any compatibility issues or any other reported/confirmed conflicts:
// TaskMaster v3.13 (or later), TaskMaster Lite v3.15 (or later)
// NetWare v5.x / v6.x / OESx (NetWare kernel)
//
// Warning:
// ========
// AS WITH ANY NEW SOFTWARE PROGRAM, BATCH SCRIPT, OR AUTOMATED PROCESSING
// PROCEDURE, CAUTION SHOULD BE EXERCISED AND DUE DILIGENCE OBSERVED DURING
// INITIAL IMPLEMENTATION. WHERE POSSIBLE, TESTING SHOULD BE PERFORMED ON
// NON-PRODUCTION SYSTEMS PRIOR TO FULL IMPLEMENTATION.
//
// Comments:
// =========
// This task script is provided free of charge and without any warranty or
// guarantee of fitness of purpose or performance.
//
// For additional TaskMaster script examples, visit the Sample Tasks page
// on the Avanti Technology, Inc. WEB Site: http://www.avanti-tech.com
//
// Note: The .HTML output is designed so that the page will automatically
// refresh (reload) approximately once per minute, in support of the
// sample task design which re-cycles (re-executes) the task and
// generates an updated .HTML page of information every minute.
//
// To remove the refresh cycle, delete the following line from the task:
// WRITE
//
// Note: Search for {MODIFY} comments indicating items which need
// to be modified or renamed (as appropriate).
//
//=============================================================================
// Check that the version of TaskMaster loaded is compatible (3.13 or later)
IF "%TM_VERSION%.%TM_SUBVERSION%"<"3.13"
// Echo the problem message to the screen
ECHO.
ECHO Error: Incompatible TaskMaster release (requires v3.13 or later)!
ECHO.
ABORT
ENDIF
// Check if already active. Terminate this copy if already active.
IF ACTIVE_TASK %TASK%
ECHO.
ECHO %TASK%: Already active! Terminating...
ECHO.
EXIT
ENDIF
// Set %0 for use as OPEN WRITE error counter
// Note: Must also be reset before restart (i.e., goto START)
DEFINE %0 0
:START
// {MODIFY} Destination (output) HTML file
// Create the output HTML page (TRUNCATE overwrites an existing copy)
OPEN WRITE SYS:\LOGIN\%TASK_FILE%.html TRUNCATE
// Check for error (WEB browser refresh conflict?) and re-try up to 3 times
IF ERRORLEVEL
IF %0<3
// Increment the error counter and re-try
DEFINE %0 %0+=1
goto START
ENDIF
ECHO.
ECHO %TASK%: Unable to create/open OPEN WRITE file for .HTML output...
ECHO Check file status and re-start task.
ECHO.
ABORT
ENDIF
// Output basic HTML template
WRITE
WRITE
WRITE
WRITE %SERVER%: Status Page
WRITE
WRITE
WRITE
WRITE
WRITE
// Output Server Status information
WRITE
WRITE
WRITE %DAY_OF_WEEK%, %MONTH_NAME% %DAY%, %YEAR%
IF %HOUR24%>12
DEFINE %1 (%HOUR24%:%MINUTE%:%SECOND%)
ELSE
DEFINE %1
ENDIF
WRITE %HOUR%:%MINUTE%:%SECOND%%AM_PM% %1
WRITE
WRITE
WRITE %SERVER%
IF "%NW_SUPPORTPACK%">""
WRITE (NetWare v%NW_VERSION%.%NW_SUBVERSION% %NW_SUPPORTPACK%)
ELSE
WRITE (NetWare v%NW_VERSION%.%NW_SUBVERSION%)
ENDIF
WRITE
:STAT_TABLE
WRITE
WRITE
WRITE
WRITE |
WRITE Up-Time:
WRITE |
WRITE
WRITE
WRITE %UPTIME_STRING%
WRITE |
WRITE
WRITE
WRITE |
WRITE Cache LRU:
WRITE |
WRITE
WRITE
WRITE %CACHE_LRU_STRING%
WRITE |
WRITE
WRITE
WRITE
WRITE
WRITE |
WRITE
IF SCREEN_LOCKED
DEFINE %1 [Locked]
ELSE
DEFINE %1
ENDIF
WRITE
WRITE |
WRITE Active Screen:
WRITE |
WRITE
WRITE
WRITE %SCREEN_NAME% %1
WRITE |
WRITE
WRITE
WRITE
WRITE
WRITE
WRITE
// ROW: Table Headings
WRITE
WRITE |
WRITE Statistic
WRITE |
WRITE
WRITE Current
WRITE |
WRITE
WRITE
WRITE | 0%
WRITE | Graph |
WRITE 100%
WRITE |
WRITE |
WRITE
// ROW: Utilization
// Set the text/graph color by value (0-50=Green, 51-89=Yellow, 90+=Red)
IF %CPU_UTIL%<=050
DEFINE %0 green
ELSEIF %CPU_UTIL%>=090
DEFINE %0 red
ELSE
DEFINE %0 yellow
ENDIF
// This logic trick strips the leading zeros from fixed format fields
DEFINE %1 0+=%CPU_UTIL%
DEFINE %4 100-=%CPU_UTIL%
WRITE
WRITE |
WRITE Utilization
WRITE |
WRITE
WRITE %1%
WRITE |
WRITE
WRITE
IF %1>000
WRITE
WRITE
WRITE |
ENDIF
IF %4>000
WRITE
WRITE
WRITE |
ENDIF
WRITE
WRITE |
WRITE
// ROW: Cache Ratio
// Set the text/graph color by value (0-50=Red, 51-74=Yellow, 75+=Green)
IF %CACHE_RATIO%>=075
DEFINE %0 green
ELSEIF %CACHE_RATIO%<=050
DEFINE %0 red
ELSE
DEFINE %0 yellow
ENDIF
// This logic trick strips the leading zeros from fixed format fields
DEFINE %1 0+=%CACHE_RATIO%
DEFINE %4 100-=%CACHE_RATIO%
WRITE
WRITE |
WRITE Cache Ratio
WRITE |
WRITE
WRITE %1%
WRITE |
WRITE
WRITE
IF %1>000
WRITE
WRITE
WRITE |
ENDIF
IF %4>000
WRITE
WRITE
WRITE |
ENDIF
WRITE
WRITE |
WRITE
// ROW: Packet Receive Buffers (PRBs)
// Pre-format %3 for fixed 3 digit result
DEFINE %3 000
// Determine the % of PRBs In Use
CALC %3 (%RECV_BUFFS_IN_USE% * 100) / %RECV_BUFFS_MAX%
// Set the text/graph color by value (0-75=Green, 76-89=Yellow, 90+=Red)
IF %3<=075
DEFINE %0 green
ELSEIF %3>=090
DEFINE %0 red
ELSE
DEFINE %0 yellow
ENDIF
// This logic trick strips the leading zeros from fixed format fields
DEFINE %1 0+=%RECV_BUFFS_IN_USE%
DEFINE %2 0+=%RECV_BUFFS_MAX%
DEFINE %4 100-=%3
WRITE
WRITE |
WRITE PktRxBuffs
WRITE |
WRITE
WRITE %1 / %2
WRITE |
WRITE
WRITE
IF %3>000
WRITE
WRITE
WRITE |
ENDIF
IF %4>000
WRITE
WRITE
WRITE |
ENDIF
WRITE
WRITE |
WRITE
// ROW: Licenses
// Note: Only applies to NetWare v4+ (each NWv3 conn equals a license)
IF %NW_VERSION%>3
// Pre-format %3 for fixed 3 digit result
DEFINE %3 000
// Determine the % of Licenses In Use (MLA returns -1 value)
IF "%LICENSES_MAX%">"0000"
CALC %3 (%LICENSES_IN_USE% * 100) / %LICENSES_MAX%
ENDIF
// Set the text/graph color by value (0-75=Green, 76-89=Yellow, 90+=Red)
IF %3<=075
DEFINE %0 green
ELSEIF %3>=090
DEFINE %0 red
ELSE
DEFINE %0 yellow
ENDIF
// This logic trick strips the leading zeros from fixed format fields
DEFINE %1 0+=%LICENSES_IN_USE%
IF NOT "%LICENSES_MAX%"=="-1"
DEFINE %2 0+=%LICENSES_MAX%
ELSE
DEFINE %2 MLA
ENDIF
DEFINE %4 100-=%3
WRITE
WRITE |
WRITE Licenses
WRITE |
WRITE
WRITE %1 / %2
WRITE |
WRITE
WRITE
IF %3>000
WRITE
WRITE
WRITE |
ENDIF
IF %4>000
WRITE
WRITE
WRITE |
ENDIF
WRITE
WRITE |
WRITE
ENDIF
// ROW: Connections
// Pre-format %3 for fixed 3 digit result
DEFINE %3 000
IF %NW_VERSION%==3
// Determine the % of Connections (i.e., Licenses) In Use
CALC %3 (%CONNS_IN_USE% * 100) / %CONNS_MAX%
// Set the text/graph color by value (0-75=Green, 76-89=Yellow, 90+=Red)
IF %3<=075
DEFINE %0 green
ELSEIF %3>=090
DEFINE %0 red
ELSE
DEFINE %0 yellow
ENDIF
ELSE
DEFINE %0 green
ENDIF
// This logic trick strips the leading zeros from fixed format fields
DEFINE %1 0+=%CONNS_IN_USE%
DEFINE %4 100-=%3
WRITE
WRITE |
WRITE Connections
WRITE |
WRITE
WRITE %1
// For NetWare v3, Max Conns is important (though irrelevant for NWv4+)
IF %NW_VERSION%==3
DEFINE %2 0+=%CONNS_MAX%
WRITE / %2
ENDIF
WRITE |
WRITE
WRITE
IF %3>000
WRITE
WRITE
WRITE |
ENDIF
IF %4>000
WRITE
WRITE
WRITE |
ENDIF
WRITE
WRITE |
WRITE
WRITE
WRITE
WRITE
WRITE
:CPU_GRAPH
WRITE
WRITE
WRITE
WRITE
WRITE |
WRITE Last Min.
WRITE |
WRITE
WRITE Utilization: Last Minute (per sec)
WRITE |
WRITE
WRITE Last Sec.
WRITE |
WRITE
WRITE |
WRITE
WRITE
WRITE
WRITE
WHILE
// Get the next CPU Utilization value (%CPU_UTIL% field)
PARSE %0 %9 1-3 PACK
IF "%0"=="" THEN BREAK
IF %0<000 OR %0>100 THEN BREAK
// Set %1 to the inverse of the CPU Utilization value for graphing
DEFINE %1 100-=%0
// Set the text/graph color by value (0-50=Green, 51-89=Yellow, 90+=Red)
IF %0<=050
DEFINE %0 green
ELSEIF %0>=090
DEFINE %0 red
ELSE
DEFINE %0 yellow
ENDIF
WRITE |
WRITE
WRITE |
// Shift the collection left by one entry
PARSE %0 %9 4-180 PACK
DEFINE %9 %0
LOOP
WRITE
WRITE |
WRITE
WRITE
WRITE
WRITE
WRITE |
WRITE Last Hour
WRITE |
WRITE
WRITE Utilization: Last Hour (avg/min)
WRITE |
WRITE
WRITE Last Min.
WRITE |
WRITE
WRITE |
WRITE
WRITE
WRITE
WRITE
// Copy cycle average collection entries to temp variable for graphing
DEFINE %2 %8
WHILE
// Get the next cycle averaged CPU Utilization value
PARSE %0 %2 1-3 PACK
IF "%0"=="" THEN BREAK
IF %0<000 OR %0>100 THEN BREAK
// Set %1 to the inverse of the CPU Utilization value for graphing
DEFINE %1 100-=%0
// Set the text/graph color by value (0-50=Green, 51-89=Yellow, 90+=Red)
IF %0<=050
DEFINE %0 green
ELSEIF %0>=090
DEFINE %0 red
ELSE
DEFINE %0 yellow
ENDIF
WRITE |
WRITE
WRITE |
// Shift the collection left by one entry
PARSE %0 %2 4-180 PACK
DEFINE %2 %0
LOOP
WRITE
WRITE |
WRITE
WRITE
WRITE Data key: Left (oldest) << Right (recent)
WRITE
WRITE
:VOL_TABLE
WRITE
WRITE
// ROW: Volume Table Headings
WRITE
WRITE |
WRITE Volume
WRITE |
WRITE
WRITE Size (MB)
WRITE |
WRITE
WRITE Used
WRITE |
WRITE
WRITE Purge
WRITE |
WRITE
WRITE Free
WRITE |
WRITE
WRITE Graph
WRITE |
WRITE
// Use VOLINFO, redirecting the output to a temporary file,
// to determine the mounted volumes
// {MODIFY} Specify the destination (temporary file) for the redirected output
VOLINFO >%TASK_PATH%\%TASK_FILE%.tmp
// {MODIFY} Read the redirected output from VOLINFO (check for errors)
OPEN READ %TASK_PATH%\%TASK_FILE%.tmp
// Check for OPEN READ errors when attempting to access the temporary file
// with the redirected VOLINFO data
IF ERRORLEVEL
WRITE
WRITE |
WRITE
WRITE VOLINFO Error: Volume data unavailable
WRITE
WRITE |
WRITE
goto EOJ
ENDIF
// Clear READ variable for WHILE/LOOP
DEFINE %0
WHILE NOT SCAN_STRING ":" "%0"
// READ first 17 bytes (16 bytes max Volume plus the colon) of next record
READ %0 1-17
// Handle a premature EOF condition (there must be at least 1 mounted volume)
IF ERRORLEVEL
WRITE
WRITE |
WRITE
WRITE READ Error: Volume data unavailable
WRITE
WRITE |
WRITE
BREAK
ENDIF
LOOP
WHILE SCAN_STRING ":" "%0"
// Strip trailing spaces from Volume name
REFORMAT %0 PACK TEXT
// ROW: Volume %0
// Change the Current Working Directory (CWD) to the Volume to check
CD %0
// Handle an error accessing the mounted volume for information retrieval
IF NOT SCAN_STRING "%VOL_NAME%" "%0"
WRITE
WRITE |
WRITE
WRITE CHDIR %0 - Error: Volume data unavailable
WRITE
WRITE |
WRITE
// READ first 17 bytes (16 bytes max Volume plus the colon) of next record
READ %0 1-17
// Check for EOF (i.e., no more records)
IF ERRORLEVEL THEN BREAK
// Resume WHILE/LOOP processing at top
CONTINUE
ENDIF
// This logic trick strips the leading zeros from fixed format fields
DEFINE %1 0+=%VOL_SIZE_MB%
DEFINE %2 0+=%VOL_USED%
DEFINE %3 0+=%VOL_PURGEABLE%
DEFINE %4 0+=%VOL_FREE%
DEFINE %4 %4-=%VOL_PURGEABLE%
WRITE
WRITE |
WRITE %0
WRITE |
WRITE
WRITE %1
WRITE |
WRITE
WRITE %2%
WRITE |
WRITE
WRITE %3%
WRITE |
WRITE
WRITE %4%
WRITE |
WRITE
WRITE
IF %2>000
WRITE
WRITE
WRITE |
ENDIF
IF %3>000
WRITE
WRITE
WRITE |
ENDIF
IF %4>000
WRITE
WRITE
WRITE |
ENDIF
WRITE
WRITE |
WRITE
// READ first 17 bytes (16 bytes max Volume plus the colon) of next record
READ %0 1-17
// Check for EOF (i.e., no more records)
IF ERRORLEVEL THEN BREAK
LOOP
:EOJ
WRITE
WRITE
WRITE
WRITE Produced by: %TASK%
WRITE Processed by: TaskMaster v%TM_VERSION%.%TM_SUBVERSION%
WRITE Time Elapsed: %ELAPSED_TIME%
WRITE
WRITE
WRITE
WRITE
WRITE
// Close the input/output files
CLOSE
// Check if collection required prior to initial WHILE/LOOP SLEEP
IF %SECOND%>00
DEFINE %0 01
DEFINE %1 0000+=%CPU_UTIL%
DEFINE %9 %CPU_UTIL%
ELSE
DEFINE %0 00
DEFINE %1 0000
DEFINE %9
ENDIF
// Pre-format the cumulative variable for cycle averaging
// This WHILE/LOOP will put the task to SLEEP for a second then collect the
// next CPU Utilization value after which it will check for a 'new' minute
// (i.e., %SECOND%==00) at which point it will BREAK out of the WHILE/LOOP
// and re-start the task (via the GOTO the label at the top)
WHILE
SLEEP 1
// Increment the cycle counter
DEFINE %0 %0+=01
// Add current value to cumulative for averaging
DEFINE %1 %1+=%CPU_UTIL%
// Append the current CPU Utilization value to the collection list
DEFINE %9 %9%CPU_UTIL%
// If it is a new minute (%SECOND%==00) then BREAK out of the WHILE/LOOP
IF %SECOND%==00 THEN BREAK
LOOP
// Pre-format the temp variable to hold the average CPU Utilization collection
DEFINE %2 000
// Calculate the average CPU Utilization for this cycle
IF %0>00
CALC %2 %1 / %0
ENDIF
// Parse previous collection to a max of 59 entries (60 total with this new one)
PARSE %3 %8 1-177 PACK
// Build new collection, prepending the current average to the collection list
DEFINE %8 %2%3
// Reset %0 for subsequent use (OPEN WRITE error counter)
DEFINE %0 0
GOTO START