Учёт установленного ПО и версий на серверах Linux

Инвентаризация сети отвечает на вопрос «что отвечает в сети». Отдельный вопрос — что установлено на каждом конкретном сервере: при выходе уязвимости в конкретной версии пакета нужно быстро узнать, на скольких серверах она есть, без захода на каждый по очереди. Ниже скрипт, который собирает список пакетов и версий с датой установки, и результаты его проверки.
Статья опирается на логику направления «Управление ИТ-активами» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами. Проверка выполнена в контейнере Debian 12, после неё всё удалено.
Что должно получиться
| Уровень | Что это значит на практике |
|---|---|
| 1. Начальный | Есть актуальный список установленного ПО по каждому серверу, с версиями, пригодный для сверки при выходе новой уязвимости |
Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.
Скрипт
#!/usr/bin/env bash
# Учёт установленного ПО и версий на хосте Debian/Ubuntu: пакеты, дата установки, срок поддержки дистрибутива.
set -uo pipefail
OUT="software-$(hostname)-$(date +%Y%m%d).csv"
echo "package,version,install_date" > "$OUT"
# дата установки берётся из лога dpkg (первая запись install для пакета); если лога нет — "unknown"
dpkg-query -W -f='${Package},${Version}\n' | while IFS=, read -r pkg ver; do
idate=$(zgrep -h " install $pkg:" /var/log/dpkg.log* 2>/dev/null | head -1 | awk '{print $1}')
echo "$pkg,$ver,${idate:-unknown}"
done >> "$OUT"
echo "готово: $OUT, пакетов: $(($(wc -l < "$OUT") - 1))"
echo "--- поддержка дистрибутива"
if command -v distro-info >/dev/null 2>&1; then
distro-info --supported 2>/dev/null | tail -1
fi
grep -E "^VERSION=" /etc/os-release
Запуск: ./sw-inventory.sh на каждом сервере (или через оркестратор конфигураций, если он есть). На выходе — CSV с именем пакета, версией и датой установки.
Результат проверки
На тестовом сервере скрипт собрал 110 пакетов. Первая попытка получить дату установки дала unknown для всех пакетов без исключения, хотя пакет был только что установлен. Причина — формат записи в журнале dpkg.log: имя пакета там идёт с архитектурой через двоеточие (install curl:amd64 …), а dpkg-query отдаёт имя без архитектуры (curl). Поиск по шаблону «пакет и пробел» не находил строку, где после имени пакета сразу стоит двоеточие. После исправления шаблона дата install корректно нашлась для пакета, установленного в рамках теста (curl,7.88.1-10+deb12u15,2026-10-14), а 88 из 110 пакетов остались с пометкой unknown — это ожидаемо: они входят в базовый образ и были установлены при его сборке, до создания файла dpkg.log в самом контейнере. На обычном сервере, где система не переустанавливалась с нуля, журнал обычно доступен за весь срок жизни машины, и доля unknown будет намного меньше.
Вторая деталь, на которую стоит обратить внимание при написании подобных скриптов: без обработки ошибки отсутствующий файл журнала (zgrep: /var/log/dpkg.log*: No such file or directory) в сочетании с set -e и pipefail останавливает весь скрипт после первой же строки без explicitного сообщения об ошибке — в текущей версии скрипта это уже учтено флагом set -uo pipefail без -e для основного цикла.
Что делать с результатом
- При выходе критической уязвимости в конкретном пакете: `grep` по имени пакета во всех собранных CSV сразу показывает, на каких серверах он есть и какой версии, без обхода серверов вручную.
- Сверяйте со сроком поддержки дистрибутива: строка
VERSIONиз/etc/os-releaseв конце отчёта показывает, не истёк ли срок поддержки самой системы — для устаревших систем вопрос не в версии пакета, а в переносе на поддерживаемый дистрибутив. - Собирайте по расписанию и храните историю: разница между вчерашним и сегодняшним списком показывает, что изменилось без явного изменения в карточке — повод свериться с процессом управления изменениями.
- Передавайте результат в процесс управления уязвимостями: список пакетов и версий — исходные данные для сопоставления с базами уязвимостей, даже без сканера.
Порядок внедрения
- Разверните скрипт на всех серверах через существующий механизм распространения конфигураций или вручную для небольшого парка.
- Настройте регулярный запуск и складывайте результаты в одно место (общая папка, внутренний репозиторий).
- При выходе критической уязвимости первым делом ищите пакет по собранным спискам, а не идите по серверам вручную.
- Сверяйте список с реестром активов: сервер, который не прислал отчёт, — повод проверить, жив ли он и не забыт ли в процессе.
- Используйте список вместе с сетевой инвентаризацией: одна показывает, что отвечает в сети, другая — что установлено на каждом хосте.
Диагностика
| Симптом | Причина и что делать |
|---|---|
| Дата установки «unknown» почти у всех пакетов | На системе давно не ротировался журнал или сервер недавно переустановлен. Ожидаемо для базового образа; на зрелом сервере проверьте, не был ли dpkg.log случайно очищен |
| Скрипт останавливается на первом пакете без сообщения об ошибке | Отсутствующий файл журнала при включённом set -e прерывает скрипт на первой неудачной подстановке. Не используйте set -e вместе с командами, у которых ожидаемо может не быть результата |
| Пакет не находится по шаблону, хотя установлен недавно | В журнале имя пакета записывается с архитектурой через двоеточие (curl:amd64). Ищите по шаблону «имя пакета и двоеточие», а не «имя пакета и пробел» |
| Нужно то же самое для RPM-дистрибутивов | Используйте rpm -qa --last для списка с датой установки; формат и источник данных другие |
Ограничения
Скрипт показывает только то, что установлено через менеджер пакетов. Приложения, развёрнутые вручную или в контейнерах со своими зависимостями, в этот список не попадают — для контейнеров нужна отдельная проверка образов: Trivy.
Где это в модели зрелости
Материал относится к направлению «Управление ИТ-активами» (материалы направления, карта зрелости). Начальный уровень требует хотя бы актуального списка ПО с версиями: без него при выходе уязвимости приходится обходить серверы вручную, теряя время на самом критичном этапе.
Как проверить
- Список установленного ПО собирается по расписанию со всех серверов, а не только по запросу.
- При выходе критической уязвимости в конкретном пакете ответ «на скольких серверах он есть» занимает минуты, а не часы.
- Сервер, переставший присылать отчёт, замечен и проверен.
- Список используется вместе с реестром активов и процессом управления уязвимостями, а не хранится отдельно без дальнейшего действия.
Источники
- Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.


















