Тут показані розбіжності між вибраною ревізією та поточною версією сторінки.
Порівняння попередніх версій Попередня ревізія | Попередня ревізія | ||
watchdog [2021/11/18 14:37] |
watchdog [2024/04/23 18:10] (поточний) nightfly [Собака-спостерігака aka Watchdog] |
||
---|---|---|---|
Рядок 1: | Рядок 1: | ||
+ | ====== Собака-спостерігака aka Watchdog ====== | ||
+ | {{: | ||
+ | |||
+ | Собака-спостерігака призначена для < | ||
+ | |||
+ | ===== Можливі перевірки ===== | ||
+ | |||
+ | ^ Типи задач | ||
+ | | icmpping | ||
+ | | tcpping | ||
+ | | udpping | ||
+ | | hopeping | ||
+ | | script | ||
+ | | httpget | ||
+ | | getusertraff | отримання кількості трафіку в байтах логіну користувача вказаного в параметрі | ||
+ | | fileexists | ||
+ | | opentickets | ||
+ | | onepunch | ||
+ | | snmpwalk | ||
+ | | freediskspace | Повертає кількість вільного місця на розділі (точці монтування) вказаній в параметрі. Повертає цифру в Гб. | float | | ||
+ | |||
+ | |||
+ | ===== Можливі оператори для перевірок ===== | ||
+ | |||
+ | ^ Оператор | ||
+ | | =true | Істинно | ||
+ | | =false | ||
+ | | == | Рівне | ||
+ | | != | Не рівне | ||
+ | | > | Більше | ||
+ | | < | Менше | ||
+ | | > = | Більше або рівне | + | | ||
+ | | < = | Менше або рівне | ||
+ | | empty | Пустий результат | | | ||
+ | | notempty | ||
+ | | changed | ||
+ | | notchanged | ||
+ | | like | Містить | ||
+ | | notlike | ||
+ | | rised | Збільшилось | ||
+ | | decreased | ||
+ | |||
+ | |||
+ | ===== Дії що будуть виконані у разі проходження умов ===== | ||
+ | |||
+ | ^ Дії | ||
+ | | log | запис події в системний лог | ||
+ | | sms | надсилання SMS сповіщення на номери стільникових, | ||
+ | | noprimary | ||
+ | | email | надсилання сповіщення електропоштою, | ||
+ | | telegram | ||
+ | | no_tg_primary | ||
+ | | andresult | ||
+ | | oldresult | ||
+ | | script | ||
+ | |||
+ | ===== Логіка роботи ===== | ||
+ | |||
+ | Кожне завдання для Собаки-спостерігаки слід сприймати як " | ||
+ | |||
+ | ^ Ім`я | ||
+ | | Гугл не пінгається | icmpping | ||
+ | |||
+ | При настанні події, коли ping на адресу google.com поверне значення " | ||
+ | |||
+ | |||
+ | А що робити, | ||
+ | |||
+ | ^ Ім`я | ||
+ | | Щось змінилось | icmpping | ||
+ | |||
+ | |||
+ | В принципі, | ||
+ | |||
+ | ^ Ім`я | ||
+ | | В серверній пожежа | script | ||
+ | |||
+ | |||
+ | Викликаючи зовнішній скрипт, | ||
+ | |||
+ | Якщо творчо підійти до парсингу виведення зовнішнього ПЗ - можна моніторити багато цікавих речей без дописування зовнішніх скриптів: | ||
+ | |||
+ | ^ Ім`я | ||
+ | | DNS зламався | ||
+ | |||
+ | Також ми можемо дуже просто та елегантно контролювати запущеність важливих сервісів типу stargazer, створивши завдання такого плану: | ||
+ | |||
+ | ^ Ім`я | ||
+ | | Stargazer впав | ||
+ | |||
+ | Хоча те саме завдання ми можемо оформити як | ||
+ | |||
+ | ^ Ім`я | ||
+ | | Stargazer впав | ||
+ | |||
+ | |||
+ | Щоб не зосереджуватись на теоретичних речах, ми можемо передбачити ситуацію, | ||
+ | |||
+ | ^ Ім`я | ||
+ | | Важливий клієнт подох | hopeping | ||
+ | |||
+ | |||
+ | Окей, а якщо ми хочемо також цю ж СМС послати скажемо адміністратору цього ж важливого клієнта, | ||
+ | |||
+ | ^ Ім`я | ||
+ | | Важливий клієнт подох | hopeping | ||
+ | |||
+ | |||
+ | а якщо ми хочемо надіслати СМС лише на додатковий номер? Так, жодних проблем: | ||
+ | | ||
+ | log,sms {+380509999999} noprimary | ||
+ | |||
+ | |||
+ | |||
+ | а якщо ми хочемо надіслати алерт тільки в додатковий чат Telegram? Так, так само без проблем: | ||
+ | | ||
+ | log, | ||
+ | | ||
+ | |||
+ | |||
+ | а можна міксувати СМС та Telegram? Так, просто вказуємо в діях все що нам потрібно разом: | ||
+ | | ||
+ | log, | ||
+ | | ||
+ | Хоча знову ж таки ніхто не забороняє нам, скажімо моніторити цього клієнта наприклад зовнішнім скриптом, | ||
+ | |||
+ | < | ||
+ | */10 * * * * / | ||
+ | </ | ||
+ | |||
+ | А ще ми можемо реагувати не лише на зміни поточних значень щодо якихось порогів, | ||
+ | |||
+ | |||
+ | ^ Ім`я | ||
+ | | Помилки полізли | onepunch | ||
+ | |||
+ | |||
+ | Ну або якийсь рівень зростання помилок ми вважаємо припустимим, | ||
+ | |||
+ | ^ Ім`я | ||
+ | | Помилки полізли активно | onepunch | ||
+ | |||
+ | |||
+ | Також ми можемо у такий спосіб відловлювати або різкі сплески або падіння утилізації, | ||
+ | ^ Ім`я | ||
+ | | Канал якось розігнався | onepunch | ||
+ | |||
+ | |||
+ | Ну чи навпаки різкі падіння щодо попередніх значень (типу утилізація аплінку провалилася на 20 гіг від останнього запуску собаки) | ||
+ | |||
+ | ^ Ім`я | ||
+ | | Трафік рухнов якось сильно | onepunch | ||
+ | |||
+ | А ще ми можемо дуже просто перевіряти робочість сервісів, | ||
+ | |||
+ | ^ Ім`я | ||
+ | | http на хості | tcpping | ||
+ | |||
+ | |||
+ | ^ Ім`я | ||
+ | | https на хості | tcpping | ||
+ | |||
+ | ^ Ім`я | ||
+ | | syslogd на хості | udpping | ||
+ | |||
+ | |||
+ | А ще ми можемо отримувати та перевіряти будь-які дані з будь-якого OID за допомогою snmpwalk: | ||
+ | |||
+ | ^ Ім`я | ||
+ | | Версія OS змінилась | snmpwalk | ||
+ | |||
+ | Або банально нотифікувати себе про те, що у кореневому розділі закінчується місце | ||
+ | |||
+ | ^ Ім`я | ||
+ | | В корені закінчується місце | freediskspace | ||
+ | |||
+ | ===== Відправка SMS ===== | ||
+ | |||
+ | Весь функціонал відправлення реалізований за допомогою підсистеми [[senddog|" | ||
+ | |||
+ | |||
+ | ===== Відсилка Telegram ===== | ||
+ | |||
+ | Здійснюється також під час проходу " | ||
+ | |||
+ | |||
+ | ===== Приклади скриптів ===== | ||
+ | |||
+ | Як вже сказано вище, за допомогою собаки-спостерігаки, | ||
+ | |||
+ | ==== Отримання трафіку з порта комутатора ==== | ||
+ | <file php switch_traffic> | ||
+ | # | ||
+ | <?php | ||
+ | |||
+ | //config section | ||
+ | $port=' | ||
+ | $oid=' | ||
+ | $ip=' | ||
+ | $community=' | ||
+ | //end of config | ||
+ | |||
+ | $cmd='/ | ||
+ | $raw=shell_exec($cmd); | ||
+ | $newTime=time(); | ||
+ | if (!empty($raw)) { | ||
+ | $raw=explode(' | ||
+ | $raw=trim($raw[1]); | ||
+ | if (!empty($raw)) { | ||
+ | $cacheName=dirname(__FILE__).'/ | ||
+ | if (file_exists($cacheName)) { | ||
+ | $oldTime=filemtime($cacheName); | ||
+ | $oldOctets=file_get_contents($cacheName); | ||
+ | $traffDiff=$raw-$oldOctets; | ||
+ | $timeDiff=$newTime-$oldTime; | ||
+ | if ($timeDiff!=0) { | ||
+ | $speed=($traffDiff*8*100)/ | ||
+ | print(round($speed/ | ||
+ | } else { | ||
+ | print(' | ||
+ | } | ||
+ | file_put_contents($cacheName, | ||
+ | } else { | ||
+ | file_put_contents($cacheName, | ||
+ | print(' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Зняття температури з ping3 ==== | ||
+ | |||
+ | <file php eping_temp> | ||
+ | # | ||
+ | <?php | ||
+ | |||
+ | $ip=' | ||
+ | $community=' | ||
+ | $oid=' | ||
+ | $result=0; | ||
+ | |||
+ | |||
+ | $command='/ | ||
+ | $resultRaw=shell_exec($command); | ||
+ | if (!empty($resultRaw)) { | ||
+ | $result=explode(' | ||
+ | $result=(isset($result[1])) ? $result[1] : 0; | ||
+ | $result=$result/ | ||
+ | } | ||
+ | |||
+ | print($result); | ||
+ | </ | ||
+ | |||
+ | ==== Наявність електомережі з ping3 ==== | ||
+ | |||
+ | <file php eping_power> | ||
+ | # | ||
+ | <?php | ||
+ | |||
+ | $ip=' | ||
+ | $community=' | ||
+ | $oid=' | ||
+ | $result=0; | ||
+ | |||
+ | |||
+ | $command='/ | ||
+ | $resultRaw=shell_exec($command); | ||
+ | if (!empty($resultRaw)) { | ||
+ | $result=explode(' | ||
+ | $result=(isset($result[1])) ? $result[1] : 0; | ||
+ | $result=($result==1) ? ' | ||
+ | } | ||
+ | |||
+ | print($result); | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== Кількість вільного місця в /var/ ==== | ||
+ | |||
+ | <file php var_stat> | ||
+ | # | ||
+ | <?php | ||
+ | $result=disk_free_space("/ | ||
+ | $result=$result/ | ||
+ | $result=round($result, | ||
+ | |||
+ | print($result); | ||
+ | ?> | ||
+ | </ | ||
+ | |||
+ | ==== Джиттер до гугла ==== | ||
+ | |||
+ | <file bash check_icmp_google> | ||
+ | #!/bin/sh | ||
+ | ping -c 1 8.8.8.8 | head -n 2 | tail -n 1 | awk -F " | ||
+ | </ | ||
+ | |||
+ | ==== Хешрейт на ethermine.org ==== | ||
+ | |||
+ | <file php ethereum_hashrate> | ||
+ | # | ||
+ | <?php | ||
+ | |||
+ | $wallet=' | ||
+ | $workersStatsUrl = ' | ||
+ | $jsonRaw = file_get_contents($workersStatsUrl); | ||
+ | $reportedHashrate = 0; | ||
+ | |||
+ | if (!empty($jsonRaw)) { | ||
+ | $workersStats = json_decode($jsonRaw, | ||
+ | if (!empty($workersStats)) { | ||
+ | foreach ($workersStats[' | ||
+ | $reportedHashrate+=$each[' | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | print(round($reportedHashrate/ | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== PPS на інтерфейсі ==== | ||
+ | |||
+ | <file bash stat_pps> | ||
+ | #!/bin/sh | ||
+ | / | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Утилізація CPU Linux хоста ==== | ||
+ | |||
+ | <file php lin_cpustats> | ||
+ | # | ||
+ | <?php | ||
+ | |||
+ | /** | ||
+ | CPU Statistics | ||
+ | |||
+ | Load | ||
+ | 1 minute Load: .1.3.6.1.4.1.2021.10.1.3.1 | ||
+ | 5 minute Load: .1.3.6.1.4.1.2021.10.1.3.2 | ||
+ | 15 minute Load: .1.3.6.1.4.1.2021.10.1.3.3 | ||
+ | |||
+ | CPU | ||
+ | percentage of user CPU time: .1.3.6.1.4.1.2021.11.9.0 | ||
+ | raw user cpu time: .1.3.6.1.4.1.2021.11.50.0 | ||
+ | percentages of system CPU time: .1.3.6.1.4.1.2021.11.10.0 | ||
+ | raw system cpu time: .1.3.6.1.4.1.2021.11.52.0 | ||
+ | percentages of idle CPU time: .1.3.6.1.4.1.2021.11.11.0 | ||
+ | raw idle cpu time: .1.3.6.1.4.1.2021.11.53.0 | ||
+ | raw nice cpu time: .1.3.6.1.4.1.2021.11.51.0 | ||
+ | |||
+ | */ | ||
+ | $oid=' | ||
+ | $ip=' | ||
+ | $community=' | ||
+ | //end of config | ||
+ | |||
+ | $cmd='/ | ||
+ | $raw=shell_exec($cmd); | ||
+ | $newTime=time(); | ||
+ | if (!empty($raw)) { | ||
+ | $raw=explode(' | ||
+ | $raw=trim($raw[1]); | ||
+ | if (!empty($raw)) { | ||
+ | print($raw); | ||
+ | } else { | ||
+ | print(' | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ===== Використання One-Punch скриптів ===== | ||
+ | |||
+ | Ще більш доцільним є використання [[onepunch|One-Punch скриптів]] замість просто скриптів, | ||
+ | |||
+ | - Вони зберігаються у вашій БД і переїжджають завжди разом із нею | ||
+ | - Вони виконуються всередині Ubilling і мають прямий доступ до всього його функціоналу. | ||
+ | |||
+ | ===== Як це працює? | ||
+ | |||
+ | Допустимо беремо і створюємо [[onepunch|One-Punch]] скрипт наступного виду: | ||
+ | |||
+ | <code php> | ||
+ | $watchdogCallbackResult=' | ||
+ | </ | ||
+ | |||
+ | Ось якось так | ||
+ | |||
+ | {{: | ||
+ | |||
+ | І припустимо ми хочемо контролювати чи не зміняться дані, що повертаються цим скриптом (з чого б це? ;) | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Сподіваюсь очевидно, | ||
+ | |||
+ | \\ | ||
+ | Також є ще одне невелике обмеження, | ||
+ | |||
+ | ==== Трафік з порта ==== | ||
+ | |||
+ | Ось наприклад те саме зняття даних про трафік з порту світча, | ||
+ | |||
+ | <code php> | ||
+ | //config section | ||
+ | $port=' | ||
+ | $oid=' | ||
+ | $ip=' | ||
+ | $community=' | ||
+ | //end of config | ||
+ | |||
+ | $cmd='/ | ||
+ | $raw=shell_exec($cmd); | ||
+ | $newTime=time(); | ||
+ | if (!empty($raw)) { | ||
+ | $raw=explode(' | ||
+ | $raw=trim($raw[1]); | ||
+ | if (!empty($raw)) { | ||
+ | $cacheName=' | ||
+ | if (file_exists($cacheName)) { | ||
+ | $oldTime=filemtime($cacheName); | ||
+ | $oldOctets=file_get_contents($cacheName); | ||
+ | $traffDiff=$raw-$oldOctets; | ||
+ | $timeDiff=$newTime-$oldTime; | ||
+ | if ($timeDiff!=0) { | ||
+ | $speed=($traffDiff*8*100)/ | ||
+ | $watchdogCallbackResult=round($speed/ | ||
+ | } else { | ||
+ | $watchdogCallbackResult=' | ||
+ | } | ||
+ | file_put_contents($cacheName, | ||
+ | } else { | ||
+ | file_put_contents($cacheName, | ||
+ | $watchdogCallbackResult=' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Вільне місце на диску ==== | ||
+ | |||
+ | <code php> | ||
+ | $result=disk_free_space("/" | ||
+ | $result=$result/ | ||
+ | $watchdogCallbackResult=round($result, | ||
+ | </ | ||
+ | |||
+ | ==== Load Average віддаленого Linux хосту ==== | ||
+ | |||
+ | <code php> | ||
+ | $oid = ' | ||
+ | $ip = ' | ||
+ | $community = ' | ||
+ | |||
+ | |||
+ | $cmd = '/ | ||
+ | $raw = shell_exec($cmd); | ||
+ | $watchdogCallbackResult = ''; | ||
+ | if (!empty($raw)) { | ||
+ | $raw = explode(' | ||
+ | $raw = trim($raw[1]); | ||
+ | if (!empty($raw)) { | ||
+ | $watchdogCallbackResult .= $raw; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Моніторинг isc-dhcpd ==== | ||
+ | |||
+ | <code php> | ||
+ | $command=' | ||
+ | $result=shell_exec($command); | ||
+ | if (!empty($result)) { | ||
+ | $watchdogCallbackResult=' | ||
+ | } else { | ||
+ | $watchdogCallbackResult=' | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ==== Моніторинг TrassirServer ==== | ||
+ | <code php> | ||
+ | $watchdogCallbackResult = ''; | ||
+ | $dvrs = new NyanORM(' | ||
+ | $dvrs-> | ||
+ | $allDvrs = $dvrs-> | ||
+ | |||
+ | if (!empty($allDvrs)) { | ||
+ | foreach ($allDvrs as $io => $each) { | ||
+ | $dvrName = $each[' | ||
+ | $trassir = new TrassirServer($each[' | ||
+ | $health = $trassir-> | ||
+ | if (!$health[' | ||
+ | $watchdogCallbackResult .= $dvrName . ' - FAILS '; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Моніторинг температури з Equicom PING3 ==== | ||
+ | |||
+ | <code php> | ||
+ | $ip = ' | ||
+ | $community = ' | ||
+ | $oid = ' | ||
+ | $correction = 0; | ||
+ | |||
+ | |||
+ | $snmp = new SNMPHelper(); | ||
+ | $resultRaw = $snmp-> | ||
+ | $watchdogCallbackResult = 0; | ||
+ | if (!empty($resultRaw)) { | ||
+ | $watchdogCallbackResult = zb_SanitizeSNMPValue($resultRaw) / 10; | ||
+ | $watchdogCallbackResult = $watchdogCallbackResult + $correction; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Моніторинг наявності живлення на Equicom PING3 === | ||
+ | <code php> | ||
+ | $ip = ' | ||
+ | $community = ' | ||
+ | $oid = ' | ||
+ | $result = 0; | ||
+ | |||
+ | |||
+ | $snmp = new SNMPHelper(); | ||
+ | $resultRaw = $snmp-> | ||
+ | $watchdogCallbackResult = 0; | ||
+ | if (!empty($resultRaw)) { | ||
+ | $watchdogCallbackResult = zb_SanitizeSNMPValue($resultRaw); | ||
+ | $watchdogCallbackResult = ($watchdogCallbackResult == 1) ? ' | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Моніторинг температур на OLT-ах === | ||
+ | |||
+ | <code php> | ||
+ | $criticalTemp = 70; | ||
+ | |||
+ | $watchdogCallbackResult = ''; | ||
+ | $tempPath = OLTAttractor:: | ||
+ | $tempExt = OLTAttractor:: | ||
+ | |||
+ | $switchesDb = new nya_switches(); | ||
+ | $switchesDb-> | ||
+ | $allOlt = $switchesDb-> | ||
+ | |||
+ | foreach ($allOlt as $io => $eachOltData) { | ||
+ | $tempData = $tempPath . $eachOltData[' | ||
+ | if (file_exists($tempData)) { | ||
+ | $oltTemp = file_get_contents($tempData); | ||
+ | if ($oltTemp >= $criticalTemp) { | ||
+ | $watchdogCallbackResult .= $eachOltData[' | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | if (empty($watchdogCallbackResult)) { | ||
+ | $watchdogCallbackResult=' | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== Нагадування про оплату TurboSMS === | ||
+ | |||
+ | <code php> | ||
+ | // ключ HTTP API | ||
+ | $apiKey = ' | ||
+ | // поріг коштів після якого нотифікувати | ||
+ | $lowerLimit = 4000; | ||
+ | |||
+ | $apiCallback = ' | ||
+ | $turboSmsApi = new OmaeUrl($apiCallback); | ||
+ | $turboSmsApi-> | ||
+ | $balanceRaw = $turboSmsApi-> | ||
+ | | ||
+ | $watchdogCallbackResult = ''; | ||
+ | if (!empty($balanceRaw)) { | ||
+ | @$balanceRaw = json_decode($balanceRaw, | ||
+ | if (!empty($balanceRaw)) { | ||
+ | if (isset($balanceRaw[' | ||
+ | if (isset($balanceRaw[' | ||
+ | $balance = $balanceRaw[' | ||
+ | if ($balance> | ||
+ | $watchdogCallbackResult.=' | ||
+ | } else { | ||
+ | $watchdogCallbackResult.=' | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </ |