Буду сваливать свои наработки, может кому пригодится. Все, где отдельно не оговорено, работает в бою.
Таймаут со времени последнего создания/изменения файлов (в пределах 24 часов).
платформа: Windows
тип: .bat
check_log.bat c:\path\to\my\files\*.txt monitorname
ECHO OFF
SET target="%1"
SET monitor=%2
SET file=%TMP%\check_file_age.%monitor%
REM в зависимости от задачи используем для DIR ключи /TC или /TW
DIR /A-D /O-D /TW %target% | FINDSTR "^[0-9]" > %file%
REM Обрабатываем ситуацию, когда нужных файлов нет вообще
DIR /A-D /O-D /TW %target%
IF %errorlevel% NEQ 0 (GOTO error)
REM Время создания/изменения самого старого файла
FOR /f "tokens=2" %%a in (%file%) do set last_time=%%a
REM Текущее время
FOR /f %%a in ('TIME /T') do set curr_time=%%a
IF %errorlevel% NEQ 0 (GOTO error)
GOTO ok
:error
DEL %file%
EXIT /B 0
:ok
SET /A ft=%last_time:~0,2%*60+%last_time:~3%
SET /A ct=%curr_time:~0,2%*60+%curr_time:~3%
IF %ct% LSS %ft% (SET /A ct=%ct%+1440)
SET /A timeout=%ct%-%ft%
opcmon %monitor%="%timeout%"
DEL %file%
EXIT /B 0
Таймаут со времени последнего создания/изменения файла с нефиксированным именем (в пределах 24 часов).
платформа: Windows
тип: .bat
varpath.bat "C:\Program Files\OVO\logs\?DD?MM?YY.log" monitor
ECHO OFF
REM ---------------------------------------------------------
REM varpath.bat target monitor
REM target - полный путь к проверяемому файлу.
REM В описании пути допустимы следующие замены:
REM ?DD - текущее число
REM ?MM - текущий месяц
REM ?YY - последние две цифры текущего года
REM ?YYYY - текущий год
REM monitor - монитор OVO
REM
REM пример:
REM varpath.bat "C:\Program Files\OVO\?DD?MM?YY.log"
REM результат:
REM C:\Program Files\OVO\251109.log
REM ---------------------------------------------------------
SETLOCAL ENABLEDELAYEDEXPANSION
SET monitor=%2
SET target=%1
SET target=!target:?DD=%DATE:~0,2%!
SET target=!target:?MM=%DATE:~3,2%!
SET target=!target:?YYYY=%DATE:~6,4%!
SET target=!target:?YY=%DATE:~8,4%!
SET target=%target:"=%
echo %target%
FOR %%I IN (%target%) DO SET target_time=%%~tI
SET fh=%target_time:~11,2%
SET fm=%target_time:~14,2%
IF %fh:~0,1% LEQ 0 (SET fh=%fh:~1,1%)
IF %fm:~0,1% LEQ 0 (SET fm=%fm:~1,1%)
SET ch=%TIME:~0,2%
SET ch=%ch: =0%
SET cm=%TIME:~3,2%
IF %ch:~0,1% LEQ 0 (SET ch=%ch:~1,1%)
IF %cm:~0,1% LEQ 0 (SET cm=%cm:~1,1%)
SET /A ft=%fh%*60+%fm%
SET /A ct=%ch%*60+%cm%
IF %ct% LSS %ft% (SET /A ct=%ct%+1440)
SET /A timeout=%ct%-%ft%
opcmon %monitor%="%timeout%"
Выполняем SQL-запрос в БД MSSQL и отсылаем результат в OVO. Буде кого не устраивают job'ы в MSSQL
платформа: Windows
тип: .bat
sql.bat DBMQSDB
ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
REM Секция описания SQL-запросов
REM Имя SQL-запроса должно совпадать с именем принимающего монитора в OVO
REM SET <MONITOR_NAME>="<SQL>"
REM -----------------------------------------------------------------------
SET DBMQSDB="SELECT COUNT(statcode) FROM inth (NOLOCK) WHERE statcode = -1 AND server = 'FOCUS' AND DETAIL <> 'INETDL' AND feidate BETWEEN GETDATE()-1 AND DATEADD(MINUTE, -5, GETDATE())"
REM ..............
REM Ну и в принципе количество запросов ничем не ограничено
REM ..............
SET ALBERTDLDTL="DECLARE @result int DECLARE @result2 int select @result = (select count(*) from [OPT].OPIUS3.dbo.dldt ) select @result2 = (select count(*) from [OP-db].OPIUS.dbo.dldt )if @result2 > @result print '1' else print '0'"
REM -----------------------------------------------------------------------
SET monitor=%1
SET sql=!%1%!
SET db=%2
REM У нас заведено, что на всех БД есть специальный стандартный пользователь для мониторинга
osql -S %db% -U USER -P PASSWORD -Q %sql% | findstr "^[^(].*[0-9]" > %TMP%\monitor_%1%.txt
FOR /f %%p IN (%TMP%\monitor_%1.txt) DO (set count=%%p)
opcmon %monitor%="%count%"
Считаем среднюю загрузку CPU процессом за определенный интервал времени. (Ловили java-процесс уходящий в бесконечную рекурсию)
платформа: *nix (HP-UX)
тип: sh
proc_cpu_util.sh monitor process timeout
#!/sbin/sh
OPC_BIN_DIR=/opt/OV/bin/OpC
OPC_CMD=$OPC_BIN_DIR/opcmon
MONITOR=$1
PROCESS=$2
TIMEOUT=$3
TMPFILE=/tmp/check_top.tmp
MAILLIST="admin@domain.net"
if [ ! $# -eq 3 ]
then
echo "Usage: proc_cpu_util.sh <monitor> <processname | username | processpid> <timeout>"
exit
fi
[ -f $TMPFILE ]&&rm $TMPFILE
PID=`ps -ef | awk '$1=="'$PROCESS'" {print $2}'`
echo $PID | grep -q " "
if [ $? -eq 0 ]
then
ERR="Some problem to get metric \"$0 $@\" on host "`hostname`
echo "$ERR" | mailx -s "$ERR" "$MAILLIST"
exit
fi
top -h -d 3 -s $TIMEOUT -n 10 -f $TMPFILE
CPU=`awk '$3=='$PID' {CPU+=$11} END {print int(CPU/3)}' $TMPFILE`
$OPC_CMD $MONITOR=$CPU
Есть список .pid файлов, необходимо проконтролировать, что они живы.
платформа: *nix (HP-UX)
тип: sh
check_pids.sh tags
#!/sbin/sh
#- setup section ------------------
OPC_BIN_DIR=/opt/OV/bin/
OPC_CMD=$OPC_BIN_DIR/opcmsg
ERROR_MAIL="admin"
HOST=`hostname`
#- procedures
send_email()
{
ERROR_CODE=$1
MSG_TXT=$2
EMAILS=$3
for I in $EMAILS
do
echo "$MSG_TXT"|mailx -s "$MSG_TXT" ${I}@domain.net
done
[ ! $ERROR_CODE -eq 0 ]&&exit $ERROR_CODE
}
#- main section -------------------
for I in $@
do
CFG=`cat $0|grep "^$I"|tr -s "\t" " "|tr -s " "`
[ ".CFG" = "." ]&&send_email 0 "$0 $I on $HOST. Error in $I" "$ERROR_MAIL"
PID_FILE=`echo $CFG|cut -f2 -d" "`
MAIL=`echo $CFG|cut -f3- -d" "`
if [ -f $PID_FILE ]
then
PID=`cat $PID_FILE`
RESULT=`ps -e|awk '{print $1}'|grep -w $PID`
if [ ".$RESULT" = "." ]
then
$OPC_CMD s=critical a=$I o=$I msg_text="$PID_FILE. Process is probably down."
send_email 0 "$PID_FILE. Process is down." "$MAIL"
fi
else
send_email 0 "$0 $I on $HOST. No $PID_FILE file" "$ERROR_MAIL $MAIL"
fi
done
exit 0
#- config
#TAG <path to pid> <emails list>
SM /opt/IBM/WebSphereAdapters/logs/connector_manager_SM_JDBC.pid admin1 admin2 adminN
FCKDR /opt/IBM/WebSphereAdapters/logs/connector_manager_FCKDR_JDBC.pid admin1 admin2 adminN
OPSPOT /opt/IBM/WebSphereAdapters/logs/connector_manager_OPSPOT_JDBC.pid admin1 admin2 adminN
PSWT /opt/IBM/WebSphereAdapters/logs/connector_manager_PSWT_JDBC.pid admin1 admin2 adminN
DM /opt/IBM/WebSphereAdapters/logs/connector_manager_DM_JDBC.pid admin1 admin2 adminN
Несколько полезных шаблонов
платформа: *nix (HP-UX)
тип: sh
Известно GLOBAL_DBNAME, надо определить ORACLE_HOME. Предполагаем, что listener.ora заполнен должным образом.
На вход подаем $DB_NAME
Перевод строки после sed 's/))(/))\ обязателен, на следующей строке текст без отступов.
for I in `ps -ex|awk '/[t]nslsnr/ {print $4":"$5}'`
do
L=`echo $I|cut -f2 -d":"`
P=`echo $I|sed 's|\(.*\)/bin/.*|\1|g'`/network/admin/listener.ora
ORACLE_HOME_TMP=`paste -s $P | tr -d " \t" | sed 's/.*SID_LIST_'"$L"'=(SID_LIST=\(.*)))\).*/\1/g' | sed 's/))(/))\
(/g' | grep "=$DB_NAME)" | sed 's/.*(ORACLE_HOME=\([^)]*\)).*/\1/'`
[ ".$ORACLE_HOME_TMP" != "." ]&&export ORACLE_HOME=$ORACLE_HOME_TMP
done
Путь до дерикторий OVO
OVPATH=`whereis ovpath | awk '{print $2}'`
OPC_CMD=`$OVPATH -instdir bin`/opcmon
OPC_INSTRUMENTATION=`$OVPATH -datadir instrumentation`
Ну и по аналогии остальное
Использую некий сводный конфиг с кучей SQL-запросов, такого вида:
#smsx_received received smsx messages#
SELECT COUNT(*)
FROM msg_log
WHERE processdate>=sysdate-1/24
AND description LIKE '%(SMSX gateway: 13)%';
#UD_job monitoring#
SELECT jobid, description
FROM int.v_mon_ud_jobs;
#
Вытащить конкретный запрос вот так: ($SQL_LIST - путь к конфигу, $SQL_SEQ - "метка" запроса)
paste -s -d" " $SQL_LIST | sed -e 's|.*#'"$SQL_SEQ"'[^#]*#\([^#]*\)#.*|\1|g' >> $SQL_TMP
SNMP для извращенцев
платформа: *nix (HP-UX)
тип: sh
в моём случае Lotus: ~70 серверов, 8 метрик с каждого
Пререквизиты:
lotus.mib - стандартный MIB для лотуса
metrics.snmp - перечесление собираемых метрик
Mail.Waiting
Mail.Dead
Mail.Hold
Server.Users
Replica.Cluster.SecondsOnQueue
Replica.Cluster.WorkQueueDepth
DataBase.DbCache.OvercrowdingRejections
Database.BufferPool.PerCentReadsInBuffer
matrix.snmp - список серверов с указанием порогов срабатывания для каждой метрики(в том порядке, как в metrics.snmp указаны)
abn_lns_001 50 50 50 0 100 100 1 95
abn_lns_002 50 50 50 0 100 100 1 95
ln1_omsk 50 50 50 0 100 100 1 95
ln2_omsk 50 50 50 0 100 100 1 95
.........................
ln1_tomsk 50 50 50 0 100 100 1 95
ln2_tomsk 50 50 50 0 100 100 1 95
ln1_kemerovo 50 50 50 0 100 100 1 95
Ну и, собственно, сам скрипт
#!/sbin/sh
cd /home/snmp
ERRLOG=./lotus_snmp_err.log
STATLOG=./lotus_snmp_stat.log
MIB=./lotus.mib
MATRIX=./matrix.snmp
METRICS=./metrics.snmp
ENTERPRISES='.1.3.6.1.4.1.' #snmp dot-префикс для lotus'а
OPC=/opt/OV/bin/opcmsg
#- functions ------------------------------------
walk()
{
HOST=$1
while read INT
do
shift
TRE=${1:-0}
[ $TRE -eq 0 ]&&continue #Если указан порог=0, то метрику не снимаем
DOT=`echo $INT | cut -f2 -d" "`
INT=`echo $INT | cut -f1 -d" " | tr "[:upper:]" "[:lower:]"`
COUNT=0
SNMP=`/opt/OV/bin/snmpwalk -c public $HOST $DOT 2>&1`
RESULT=`echo $SNMP | awk '{print $4}'`
if [ `echo $RESULT|grep "[a-zA-Z]"` ] #Разбираем ответ
then
echo `date "+%D %T"`" $HOST $DOT $INT $SNMP" >> $ERRLOG
RESULT=-1
$OPC severity=major application=lotus object=snmp msg_grp=lotus service_id="$HOST" msg_text="$HOST: Problem with lotus snmp agent ($SNMP)"
fi
if [ $RESULT -ge $TRE ]
then
$OPC severity=critical application=lotus object=snmp msg_grp=lotus service_id="$HOST" msg_text="$HOST: $INT > $TRE"
fi
echo `date "+%D %T"`" $HOST $INT $RESULT" >> $STATLOG
done < $METRICS.tmp
exit 0
}
#- main -----------------------------------------
[ $# -gt 0 ]&&walk $@ #Если скрипт запущен с параметром, то дальше не идем, а опрашиваем ноду
>$METRICS.tmp
while read INT #Определяем dot-представление для каждой метрики
do
INT=`echo $INT | tr "[:upper:]" "[:lower:]"`
NODE=`paste -s -d" " $MIB | sed -e 's|.*INT '$INT' [^{]*{\([^}]*\)}.*|\1|g'`
DOT=`echo $NODE|cut -f2 -d" "`
NODE=`echo $NODE|cut -f1 -d" "`
COUNT=0
while [ ! "$NODE" = "enterprises" ]
do
NODE=`grep "^$NODE " $MIB | awk '{print $6" "$7}'`
DOT=`echo $NODE|cut -f2 -d' '`.$DOT
NODE=`echo $NODE|cut -f1 -d' '`
COUNT=`expr $COUNT + 1`
[ $COUNT -eq 20 ]&&break
done
echo $INT $ENTERPRISES$DOT >> $METRICS.tmp
done < $METRICS
grep -v '^#' $MATRIX > $MATRIX.tmp #Формируем актуальный список серверов
while read LINE #Держим параллельно запущенными 10 сессий
do
while [ `ps -ef|fgrep -c $0` -gt 10 ]
do
sleep 1
done
$0 $LINE &
done < $MATRIX.tmp
OpenView Operations
Контроль за кошерностью дежурной смены.
количество пришедших сообщений/ время создания/ время реакции дежурного/ скорость реакции.
Все времена округлены до 30м отрезков. USERNAME=логин дежурного. Только критические сообщения, меняется условием AND a.severity=
SELECT
COUNT(*) AS messages,
creation_time,
ackn_time,
reaction_time
FROM
(
SELECT
TO_CHAR(TO_DATE('01011970','mmddyyyy') + TRUNC(a.creation_time/1800)/48, 'dd/mm/yy hh24:mi') AS creation_time,
TO_CHAR(TO_DATE('01011970','mmddyyyy') + TRUNC(a.ackn_time/1800)/48, 'dd/mm/yy hh24:mi') AS ackn_time,
TO_CHAR(TO_DATE('01011970','mmddyyyy') + TRUNC((a.ackn_time-a.receiving_time)/1800)/48, 'hh24:mi') AS reaction_time
FROM opc_op.opc_hist_messages a, opc_op.opc_node_names b, opc_op.opc_nodes_in_group c, opc_op.opc_hist_msg_text d
WHERE a.node_id=b.node_id
AND a.node_id=c.node_id
AND a.message_number=d.message_number
AND a.severity=8
AND a.message_group||c.node_group_id IN
(
SELECT msg_group_name||node_group_id
FROM opc_op.opc_op_realm
WHERE user_id=
(
SELECT user_id FROM opc_op.opc_user_data WHERE name='USERNAME'
)
)
)
GROUP BY creation_time, ackn_time, reaction_time
ORDER BY creation_time
OpenView Operations
Как правильно указывать VBScritp в monitor->program
%systemroot%\\system32\\cscript.exe "%OvDataDir%\\bin\\instrumentation\\script.vbs"
Проверяем наличие процесса process, запущенного от имени user.
По умолчанию использует opcmsg, но ключем -m можно форсировать opcmon.
Ну и другие разные плюшки.
платформа: *nix (HP-UX)
Usage: process_by_user.sh -p process [ -u user ] [ -e "emails" ] [ -m monitor ] [ -g msg_grp ] [ -a application ] [ -t "msg_text" ]
Default: user = root
msg_grp = Application
application = $user
msg_text = Process $process of user $user on server $host is down
In msg_text may usage keys:
%p->$process
%u->$user
%h->$hostname
#!/usr/bin/sh
#-- environment
OVPATH=`whereis ovpath | awk '{print $2}'`
OPC_CMD=`$OVPATH -instdir bin`/opcmsg
SELF_NAME=`echo $0 | sed -e 's|^.*/||' -e 's|\.sh$||'`
DOMAIN="domain.ru"
USER=root
MSG_GRP=Application
HOST=`hostname`
while getopts p:u:e:m:g:a:t: OPT
do
case $OPT in
p) PROCESS=$OPTARG;;
u) USER=$OPTARG;;
e) MAIL_LIST=$OPTARG;;
m) MONITOR=$OPTARG
OPC_CMD=`$OVPATH -instdir bin`"/opcmon $MONITOR=1"
;;
g) MSG_GRP=$OPTARG;;
a) APPLICATION=$OPTARG;;
t) MSG_TEXT=$OPTARG;;
esac
done
if [ "$MSG_TEXT." = "." ]
then
MSG_TEXT="Process $PROCESS of user $USER on server $HOST is down"
else
PROCESS_SED=`echo $PROCESS | sed -e 's|\.|\\\.|g' -e 's/|/\\\|/g'`
MSG_TEXT=`echo $MSG_TEXT | sed -e 's|%p\([,\. ]\)|'"$PROCESS_SED"'\1|g' -e 's|%u\([,\. ]\)|'$USER'\1|g' -e 's|%h\([,\. ]\)|'$HOST'\1|g'`
fi
if [ "$APPLICATION." = "." ]
then
APPLICATION=$USER
fi
if [ "$OPC_ARG." = "." ]
then
OPC_ARG="s=critical a=$APPLICATION o=process msg_grp=$MSG_GRP"
fi
if [ "$PROCESS." = "." ]
then
echo " Usage: process_by_user.sh -p process [ -u user ] [ -e \"emails\" ] [ -m monitor ] [ -g msg_grp ] [ -a application ] [ -t \"msg_text\" ]"
echo "Default: user = root"
echo " msg_grp = Application"
echo " application = \$user"
echo " msg_text = Process \$process of user \$user on server \$host is down"
echo " In msg_text may usage keys:"
echo " %p->\$process"
echo " %u->\$user"
echo " %h->\$hostname"
exit 1
fi
#-- main
ps -fu $USER | grep "$PROCESS" | grep -qve grep -e "$SELF_NAME"
if [ $? -ne 0 ]
then
if [ "$MONITOR." = "." ]
then
$OPC_CMD s=critical a=$APPLICATION o=process msg_grp=$MSG_GRP msg_text="$MSG_TEXT"
else
$OPC_CMD
fi
if [ ! "$MAIL_LIST." = "." ]
then
echo $MAIL_LIST | grep -q "@"
if [ $? -ne 0 ]
then
MAIL_LIST=`echo " $MAIL_LIST " | sed 's/ / /g' | sed 's/ \([^ ][^ ]*\) / \1@'$DOMAIN' /g'`
fi
echo $MSG_TEXT | mailx -s "$MSG_TEXT" $MAIL_LIST
fi
fi
Для того, чтобы при форвардинге сообщений не дублировалась почтовая рассылка, взводим на серверах переменную
ovconfchg -ns opc -set OPC_TT_SHOW_FORW_MGR TRUE
Перечитываем конфигурацию
добавляем в /opt/OV/bin/OpC/extern_intf/ttns_mail.sh строку
if [ $# -gt 0 ]
then
forward_mgr=$1
shift
exit 0 # <<<<<<<<<<<<<<<<<
else
forward_mgr="<none>"
fi
Вычисляем список рассылки по конкретной ноде и конкретной msg_grp
SELECT DISTINCT(B.NAME), C.NODE_GROUP_NAME
FROM opc_op_realm a, opc_user_data b
WHERE 1=1
AND A.MSG_GROUP_NAME = 'MSG_GROUP_NAME'
AND A.NODE_GROUP_ID IN
(
SELECT NODE_GROUP_ID
FROM OPC_NODES_IN_GROUP
WHERE NODE_ID =
(
SELECT NODE_ID
FROM OPC_NODE_NAMES
WHERE NODE_NAME='NODE_NAME'
)
)
AND A.USER_ID=B.USER_ID
ORDER BY B.NAME