Що ми отримаємо
Щотижня сервер або робоча станція надсилатиме короткий звіт на email: скільки пакетів оновлюється, чи є безпекові оновлення та чи знайдені critical/high уразливості. Основні цілі:
- Автоматичний збір інформації через APT про оновлення Linux;
- Скан критичних CVE (через
debsecan); - Надсилання результату поштою або логування на випадок, якщо пошта не налаштована;
- Запуск раз на тиждень через systemd timer.
Основний How‑to: bash-скрипт + systemd service/timer
1) Встановіть залежності
Пакет mailutils дасть команду mail для надсилання листів, а debsecan підкаже про відомі CVE для встановлених пакетів.
sudo apt update
sudo apt install -y mailutils debsecan
2) Створіть скрипт /usr/local/bin/weekly-apt-alert.sh
Скрипт оновлює індекси APT, рахує upgradable пакети, виділяє security-оновлення та, якщо доступний debsecan, збирає критичні/високі CVE. Потім надсилає звіт на email.
sudo tee /usr/local/bin/weekly-apt-alert.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
umask 027
ALERT_EMAIL="root" # Змініть на вашу адресу, напр. ops@example.com
HOST="$(hostname -f || hostname)"
MAIL_BIN="$(command -v mail || command -v mailx || command -v s-nail || true)"
DEBSECAN="$(command -v debsecan || true)"
LOG_FILE="/var/log/weekly-apt-alert.log"
# Оновлюємо індекси APT (тихо)
apt-get update -qq || apt update -qq || true
# Список оновлень
UPGR_LIST="$(apt list --upgradable 2>/dev/null | tail -n +2 || true)"
UPGR_COUNT=$(printf "%s\n" "$UPGR_LIST" | sed '/^$/d' | wc -l | tr -d ' ')
# Безпекові оновлення (репозиторій *security*)
SEC_LIST=$(printf "%s\n" "$UPGR_LIST" | grep -i security || true)
SEC_COUNT=$(printf "%s\n" "$SEC_LIST" | sed '/^$/d' | wc -l | tr -d ' ')
# Критичні/високі CVE (якщо є debsecan)
CVE_SECTION=""
CVE_COUNT=0
if [[ -n "$DEBSECAN" ]]; then
# Показуємо лише виправлені уразливості для встановлених пакетів
CVE_RAW="$($DEBSECAN --only-fixed --severity critical,high --format detail 2>/dev/null || true)"
CVE_COUNT=$(printf "%s\n" "$CVE_RAW" | grep -E '^CVE-' | wc -l | tr -d ' ')
if [[ $CVE_COUNT -gt 0 ]]; then
CVE_SECTION=$(printf "\nTop critical/high CVE (перші 20):\n%s\n" "$(printf "%s\n" "$CVE_RAW" | head -n 200)")
else
CVE_SECTION="\nКритичних/високих CVE не виявлено."
fi
else
CVE_SECTION="\ndebsecan не встановлено — пропущено перевірку CVE (apt install debsecan)."
fi
NOW="$(date -Is)"
REPORT=$(cat <<RPT
[Weekly APT/Security report]
Host: $HOST
Time: $NOW
Оновлень доступно: $UPGR_COUNT
З них безпекових (*security*): $SEC_COUNT
Критичних/високих CVE: $CVE_COUNT
Оновлення (перші 30):
$(printf "%s\n" "$UPGR_LIST" | head -n 30)
Безпекові оновлення (перші 30):
$(printf "%s\n" "$SEC_LIST" | head -n 30)
=== CVE ===
$CVE_SECTION
RPT
)
# Надсилання звіту
if [[ -n "$MAIL_BIN" ]]; then
printf "%s\n" "$REPORT" | "$MAIL_BIN" -s "[$HOST] Weekly APT & Security report" "$ALERT_EMAIL" || true
else
echo "$NOW [WARN] Mailer not found, writing to $LOG_FILE" | tee -a "$LOG_FILE" 1>/dev/null
fi
# Дублюємо у системний журнал і файл логів
logger -t weekly-apt-alert -- "$HOST: updates=$UPGR_COUNT security=$SEC_COUNT cve=$CVE_COUNT"
{
echo "==== $NOW ===="
echo "$REPORT"
} >> "$LOG_FILE"
echo "Done"
EOF
sudo chmod 750 /usr/local/bin/weekly-apt-alert.sh
sudo chown root:root /usr/local/bin/weekly-apt-alert.sh
3) Створіть systemd service і timer
Сервіс запускає скрипт один раз, а таймер — за розкладом щонеділі о 08:00 з випадковою затримкою до години (щоб тисячі машин не писали одночасно).
# Service
sudo tee /etc/systemd/system/weekly-apt-alert.service >/dev/null <<'EOF'
[Unit]
Description=Weekly APT updates & CVE email alert
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
# Захист від одночасних запусків
ExecStart=/usr/bin/flock -n /run/weekly-apt-alert.lock /usr/local/bin/weekly-apt-alert.sh
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=7
PrivateTmp=yes
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
EOF
# Timer (щонеділі о 08:00)
sudo tee /etc/systemd/system/weekly-apt-alert.timer >/dev/null <<'EOF'
[Unit]
Description=Run weekly-apt-alert.service weekly
[Timer]
OnCalendar=Sun 08:00
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now weekly-apt-alert.timer
# Перша ручна перевірка
sudo systemctl start weekly-apt-alert.service
sudo systemctl status weekly-apt-alert.service --no-pager
journalctl -u weekly-apt-alert.service -n 100 --no-pager
Готово! Тепер у вас автоматичні щотижневі звіти про оновлення Linux і безпекові ризики.
Альтернативні способи
- cron замість systemd: якщо дуже треба, додайте в root crontab:
@weekly /usr/local/bin/weekly-apt-alert.sh. Але systemd timers надійніші (логування, залежності, Persistent=). - apticron:
sudo apt install apticron— шле щоденні листи про оновлення. Можна зменшити частоту через systemd timer або cron. - unattended-upgrades: для автоматичної установки security-оновлень і (опційно) email-звітів. Добре поєднується з нашим звітом для подвійного контролю.
GUI-спосіб (робочий стіл)
Хочете просто нагадування на стільниці? Зробіть користувацький timer з нотифікацією notify-send ⏰
mkdir -p ~/.local/bin
tee ~/.local/bin/weekly-apt-notify.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
apt-get update -qq || true
UP=$(apt list --upgradable 2>/dev/null | tail -n +2 | wc -l | tr -d ' ')
notify-send "APT: доступні оновлення" "$UP пакет(ів) чекають на оновлення" -i software-update-available
EOF
chmod +x ~/.local/bin/weekly-apt-notify.sh
# user service
mkdir -p ~/.config/systemd/user
tee ~/.config/systemd/user/weekly-apt-notify.service >/dev/null <<'EOF'
[Unit]
Description=Weekly desktop APT notify
[Service]
Type=oneshot
ExecStart=%h/.local/bin/weekly-apt-notify.sh
EOF
tee ~/.config/systemd/user/weekly-apt-notify.timer >/dev/null <<'EOF'
[Unit]
Description=Run weekly-apt-notify.service weekly
[Timer]
OnCalendar=Sun 09:00
Persistent=true
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable --now weekly-apt-notify.timer
FAQ
Листи не приходять. Що робити?
Перевірте, чи є mail/mailx: command -v mail. Якщо ні — sudo apt install -y mailutils. На серверах без MTA налаштуйте postfix (режим Satellite/Smarthost) або легкий msmtp з SMTP вашого провайдера.
Як змінити адресу одержувача?
Відредагуйте змінну ALERT_EMAIL у скрипті та перезапустіть сервіс: sudo systemctl start weekly-apt-alert.service.
Як змінити час або день?
У файлі таймера змініть OnCalendar=Sun 08:00 на бажане, наприклад Mon *-*-* 07:30. Потім: sudo systemctl daemon-reload && sudo systemctl restart weekly-apt-alert.timer.
Звіт порожній, а оновлення точно є!
Команда apt list --upgradable іноді кешує старі дані — спробуйте вручну: sudo apt-get update і перевірте ще раз. Також гляньте journalctl -u weekly-apt-alert.service.
Чому не використали лише cron?
systemd timers краще логуються, підтримують Persistent= (пропущені старти при простої), а також обмеження ресурсів і sandboxing. Але cron — робоча альтернатива.
Чи коректний debsecan для Ubuntu?
Переважно так, але джерело CVE — Debian Security Tracker. Для Ubuntu інколи імена пакетів/версій відрізняються. Все одно це корисний сигнал. Хочете 100% для Ubuntu — додайте перевірку через ubuntu-security-status (пакет update-notifier-common), як альтернативу.
Можна додати автоінсталяцію security-оновлень?
Так. Встановіть unattended-upgrades і дозвольте security-покети. Наш звіт тоді радше підтверджуватиме стан.
Порада від Kernelka
Зробіть репетицію: одразу після налаштування запустіть сервіс вручну й переконайтеся, що лист дійшов. Ще класно додати у timer параметр RandomizedDelaySec= (ми вже додали) — це зменшує пікове навантаження на дзеркала APT і ваш SMTP 😊
Підсумок
- Встановили інструменти для звітів і CVE:
mailutils,debsecan. - Створили надійний bash-скрипт із логуванням та email-оповіщенням.
- Налаштували systemd service + weekly timer з захистом від колізій.
- Розглянули альтернативи: cron, apticron, unattended-upgrades, а також GUI-нагадування.
- Тепер ви контролюєте оновлення Linux і критичні уразливості — спокійніше спиться!

Прокоментувати
На сайті відображається лише твоє ім'я та коментар. Електронна пошта зберігається виключно для зв'язку з тобою за потреби та в жодному разі не передається стороннім особам.