Будем использовать Zabbix для слежения за списком установленных программ.
Замечание 1.
Способ установки Python 2.7 описан тут: https://www.mihanik.net/tihaja-ustanovka-python-2-7/
Замечание 2.
Способ становки Zabbix-агента (клиента) описан тут: https://www.mihanik.net/ustanovka-zabbix-klienta/
1. Собираем данные по установленным программам при помощи скрипта.
Скрипт написан на Python 2.7, он собирает данные по установленным программам и формирует 2 файла:
-
- непосредственно сам список установленных программ — C:\Zabbix\scripts\soft_list\soft_list.lst
- список изменений в установленных программах (что удалено/установлено) — C:\Zabbix\scripts\soft_list\soft_diff.lst
Скрипт сохранён под именем C:\Zabbix\scripts\soft_list\programmlist.py.
Текст скрипта:
# -*- coding: utf-8 -*-
import os
import sys
import ctypes
import errno
import _winreg
import codecs
#
# Функция проверки наличия прав администратора
# Вход: нет
# Выход: true - есть права администратора,
# false - нет прав администратора
#
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
#
# Функция удаления дубликатов из списка
# Вход: список
# Выход: список без дубликатов
#
def DuplicateRemoval ( InboundList ):
OutboundList = []
for i in InboundList:
if i not in OutboundList:
OutboundList.append(i)
return OutboundList
#
# Функция загрузки списка из файла
# Вход: путь к файлу со списком
# Выход: список
#
def ListLoad ( InboundFileName ):
OutboundList = []
# Если указанного файла не существует возвращаем пустой список
if not os.path.exists( InboundFileName ):
return OutboundList
if not os.path.isfile( InboundFileName ):
return OutboundList
# Читаем файл построчно
f = open( InboundFileName,'r')
try:
OutboundList = f.read().splitlines()
except Exception:
pass
finally:
f.close()
return OutboundList
#
# Функция сохранения списка в файл
# Вход: список, путь к файлу
# Выход: true - успешная запись, false - ошибка при записи
#
def ListSave ( OutboundList, OutboundFileName ):
# Записываем файл построчно
f = open( OutboundFileName,'w')
try:
for line in OutboundList:
f.write(line + '\n')
except Exception:
MyResult = False
else:
MyResult = True
finally:
f.close()
return MyResult
#
# Функция получения списка установленных программ
# Вход: нет
# Выход: список установленных программ
#
def ProgramList():
# Определим разрядность системы
try:
os.environ["PROGRAMFILES(X86)"]
proc_arch = 64
except:
proc_arch = 32
# Зададим режимы просмотра реестра
if proc_arch == 32:
arch_keys = []
elif proc_arch == 64:
arch_keys = [ _winreg.KEY_WOW64_32KEY, _winreg.KEY_WOW64_64KEY ]
# Зададим ветки реестра, где нужно искать информацию об установленных программах
keys = [ r'hklm\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
r'hklm\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall',
r'hkcu\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall']
List = []
for arch_key in arch_keys:
for MyKey in keys:
# ветки hkcu\...\Uninstall может не быть. Предусмотрим вероятность срабатывания исключения
try:
if 'hkcu' not in MyKey:
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, MyKey[5:], 0, _winreg.KEY_READ | arch_key)
else:
key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, MyKey[5:], 0, _winreg.KEY_READ | arch_key)
except Exception:
pass
else:
for i in xrange(0, _winreg.QueryInfoKey(key)[0]):
skey_name = _winreg.EnumKey(key, i)
skey = _winreg.OpenKey(key, skey_name)
try:
List.append ( _winreg.QueryValueEx(skey, 'DisplayName')[0] )
except OSError as e:
if e.errno == errno.ENOENT:
# DisplayName не существует в этом разделе
pass
finally:
skey.Close()
List.sort()
NewList = DuplicateRemoval (List)
return NewList
################################################################################
# Начало программы
################################################################################
def main(argv=None):
# Проверяем наличие прав админа.
if not is_admin ():
sys.exit ('Not enough permissions to run the script !!!')
# Устанавливаем кодировку по умолчанию.
reload(sys)
sys.setdefaultencoding('utf8')
# Зададим имена файлам, которые будем использовать
MySoftListFile=r'C:\Zabbix\scripts\soft_list\soft_list.lst'
MySoftDiffFile=r'C:\Zabbix\scripts\soft_list\soft_diff.lst'
# Получаем список установленных программ
List = ProgramList()
# Получаем прежний список из файла
OldList = ListLoad ( MySoftListFile )
# Ищем установленные/удалённые программы
DeletedList = []
InstalledList = []
# Получаем список свежеустановленных программ
for i in List:
if i not in OldList:
InstalledList.append(i)
# Получаем список удалённых программ
for i in OldList:
if i not in List:
DeletedList.append(i)
# Сохраняем список изменений в diff-файл построчно
f = open( MySoftDiffFile,'w')
try:
f.write('Deleted:'+ '\n')
for line in DeletedList:
f.write(line + '\n')
f.write('\n')
f.write('Installed:'+ '\n')
for line in InstalledList:
f.write(line + '\n')
except Exception:
pass
finally:
f.close()
# Сохраняем текущий список установленных программ в файл
if not ListSave (List, MySoftListFile):
sys.exit ('Unable to save installed program list!!!')
if __name__ == "__main__":
sys.exit(main())
2. Устанавливаем скрипт в системе.
Скрипт лучше запускать каждый час, — не слишком часто, но и не слишком редко.
Запланировать выполнение скрипта можно при помощи планировщика Windows. Задание планировщика можно создать вручную, а можно и при помощи bat-файла.
Я обычно это делаю при помощи «батника», имя своему батнику я дал C:\Zabbix\scripts\soft_list\INSTALL_get_soft_list.bat .
Текст скрипта:
@echo off
Rem Предполагаем, что на Windows XP скрипт запускается администратором.
Rem Для более старших систем это неверно.
rem Получаем версию ОС
ver | find "5.1."
rem Windows XP ?
If %errorlevel%==0 (
rem Пропускаем проверку админских прав
GOTO SKIPADMIN
)
SET HasAdminRights=0
FOR /F %%i IN ('WHOAMI /PRIV /NH') DO (
IF "%%i"=="SeTakeOwnershipPrivilege" SET HasAdminRights=1
)
IF NOT %HasAdminRights%==1 (
ECHO .
ECHO Not enough permissions to run the script !!!
ECHO .
GOTO END
)
:SKIPADMIN
rem Получаем версию ОС
rem Windows XP ?
ver | find "5.1."
If %errorlevel%==0 (
rem Windows XP
SCHTASKS /Create /RU "NT AUTHORITY\SYSTEM" /SC HOURLY /ST 00:00:00 /TN "InstalledSoftware" /TR "python \"C:\zabbix\scripts\soft_list\programmlist.py\""
) else (
rem НЕ Windows XP
SCHTASKS /Create /RU "NT AUTHORITY\SYSTEM" /SC DAILY /ST 00:00 /RI 60 /DU 24:00 /TN "InstalledSoftware" /TR "python \"C:\zabbix\scripts\soft_list\programmlist.py\"" /RL HIGHEST /F
)
cd "C:\Zabbix\scripts\soft_list"
python "C:\zabbix\scripts\soft_list\programmlist.py"
:END
EXIT /B
3. Формируем шаблон в Zabbix.
В Zabbix при этом добавляем несложный шаблон.
Сначала приведу описание шаблона в картинках.
Имя шаблона: Active Computer — Python — ProgramList…
Добавляем группу элементов данных…
Теперь добавляем 3 элемента данных…
И, наконец, несложный триггер, который будет срабатывать при изменении списка программ…
А вот и готовый для импорта заархивированный файл с описанным выше шаблоном: zbx_export_template_programlist.xml
Описанные ранее скрипты можно найти в этом архиве: soft_list
4. Сбор данных.
Осталось назначить созданный шаблон соответствующему узлу сети и ждать начала поступления данных. 🙂
Всё.
🙂