mirror of
https://github.com/andrey271192/safe-monthly-maintenance.git
synced 2026-09-20 11:55:33 +00:00
299 lines
11 KiB
Markdown
299 lines
11 KiB
Markdown
# Safe Monthly Maintenance
|
||
|
||
Безопасное ежемесячное обслуживание Ubuntu/Debian одной командой.
|
||
|
||
Скрипт устанавливает systemd timer, обновляет пакеты без `dist-upgrade`, чистит
|
||
безопасные кэши и журналы, проверяет состояние `dpkg`, свободное место и
|
||
необходимость перезагрузки. Автоматическая перезагрузка, `autoremove` и очистка
|
||
Docker выключены по умолчанию.
|
||
|
||
> Проверено на Debian 12. Скрипт рассчитан на Ubuntu и Debian с systemd и APT.
|
||
> Перед массовым развертыванием проверьте его на одной тестовой VM.
|
||
|
||
## Установка одной командой
|
||
|
||
Закрепленная версия:
|
||
|
||
```bash
|
||
curl -fsSL https://raw.githubusercontent.com/andrey271192/safe-monthly-maintenance/v1.0.2/install.sh | sudo bash -s -- --run-now
|
||
```
|
||
|
||
Команда:
|
||
|
||
1. скачивает `install.sh`;
|
||
2. устанавливает maintenance-скрипт и systemd units;
|
||
3. включает ежемесячный timer;
|
||
4. сразу выполняет первое обслуживание.
|
||
|
||
Установка без немедленного запуска:
|
||
|
||
```bash
|
||
curl -fsSL https://raw.githubusercontent.com/andrey271192/safe-monthly-maintenance/v1.0.2/install.sh | sudo bash
|
||
```
|
||
|
||
Если `curl` отсутствует:
|
||
|
||
```bash
|
||
wget -qO- https://raw.githubusercontent.com/andrey271192/safe-monthly-maintenance/v1.0.2/install.sh | sudo bash -s -- --run-now
|
||
```
|
||
|
||
## Более безопасная установка с проверкой
|
||
|
||
Не запускайте неизвестный код от `root` вслепую. Скачайте, проверьте, затем
|
||
выполните:
|
||
|
||
```bash
|
||
curl -fsSL https://raw.githubusercontent.com/andrey271192/safe-monthly-maintenance/v1.0.2/install.sh -o /tmp/install-safe-maintenance.sh
|
||
sha256sum /tmp/install-safe-maintenance.sh
|
||
less /tmp/install-safe-maintenance.sh
|
||
sudo bash /tmp/install-safe-maintenance.sh --run-now
|
||
```
|
||
|
||
SHA-256 версии `v1.0.2`:
|
||
|
||
```text
|
||
247312aaca5eb5b40c8893edb065203b2e4f0121c47421d85b46f9ae46770367
|
||
```
|
||
|
||
## Что устанавливается
|
||
|
||
| Путь | Назначение |
|
||
|---|---|
|
||
| `/usr/local/sbin/safe-monthly-maintenance` | Основной maintenance-скрипт |
|
||
| `/etc/default/safe-monthly-maintenance` | Настройки конкретной VM |
|
||
| `/etc/systemd/system/safe-monthly-maintenance.service` | Одноразовый systemd service |
|
||
| `/etc/systemd/system/safe-monthly-maintenance.timer` | Ежемесячный запуск |
|
||
| `/var/backups/safe-monthly-maintenance/` | Снимки списка пакетов |
|
||
|
||
Повторный запуск installer обновляет скрипт и units, но сохраняет существующий
|
||
файл настроек.
|
||
|
||
## Расписание
|
||
|
||
Timer запускается первого числа каждого месяца в 03:00 с случайной задержкой до
|
||
шести часов:
|
||
|
||
```ini
|
||
OnCalendar=*-*-01 03:00:00
|
||
RandomizedDelaySec=6h
|
||
Persistent=true
|
||
```
|
||
|
||
Случайная задержка уменьшает одновременную нагрузку на репозитории, если один
|
||
installer установлен на много VM. `Persistent=true` выполняет пропущенный запуск
|
||
после включения сервера.
|
||
|
||
## Что делает обслуживание
|
||
|
||
### 1. Проверяет окружение
|
||
|
||
- требует права `root`;
|
||
- разрешает только Ubuntu/Debian и Debian-подобные системы;
|
||
- использует `flock`, поэтому два запуска не идут одновременно;
|
||
- использует ожидание APT-lock до 600 секунд;
|
||
- повторяет сетевые обращения APT до трех раз.
|
||
|
||
### 2. Сохраняет список пакетов
|
||
|
||
Перед обновлением выполняется:
|
||
|
||
```bash
|
||
dpkg --get-selections
|
||
```
|
||
|
||
Снимок записывается в `/var/backups/safe-monthly-maintenance/`. Снимки старше
|
||
120 дней удаляются. Это не полный rollback системы, но помогает восстановить
|
||
состав пакетов.
|
||
|
||
### 3. Чистит только безопасные данные
|
||
|
||
- `systemd-tmpfiles --clean` — применяет штатные политики очистки временных
|
||
файлов;
|
||
- `logrotate` — запускает штатную ротацию логов;
|
||
- `journalctl --vacuum-time=30d` — удаляет старый journal;
|
||
- `journalctl --vacuum-size=500M` — ограничивает размер journal;
|
||
- `apt-get autoclean` — удаляет устаревшие package-файлы;
|
||
- `apt-get clean` — очищает скачанный APT-кэш после обновления.
|
||
|
||
Скрипт не выполняет ручной `rm -rf` для `/tmp`, `/var/log`, Docker volumes или
|
||
пользовательских каталогов.
|
||
|
||
### 4. Проверяет пакетную систему
|
||
|
||
`dpkg --audit` запускается до обновления. Если пакетная операция была прервана,
|
||
обновление пропускается. Скрипт не пытается автоматически ремонтировать
|
||
неоднозначное состояние.
|
||
|
||
После обновления выполняется:
|
||
|
||
```bash
|
||
apt-get check
|
||
```
|
||
|
||
### 5. Проверяет свободное место
|
||
|
||
Обновление пропускается, если:
|
||
|
||
- на `/` осталось меньше 1 ГиБ;
|
||
- на отдельном `/boot` осталось меньше 200 МиБ.
|
||
|
||
Порог можно изменить в конфигурации.
|
||
|
||
### 6. Обновляет пакеты
|
||
|
||
Используется:
|
||
|
||
```bash
|
||
apt-get -y \
|
||
-o Dpkg::Options::=--force-confold \
|
||
--with-new-pkgs \
|
||
--no-remove \
|
||
upgrade
|
||
```
|
||
|
||
Почему:
|
||
|
||
- `upgrade`, не `dist-upgrade`/`full-upgrade`: пакеты не удаляются;
|
||
- `--with-new-pkgs`: разрешает новые зависимости, включая новое ядро;
|
||
- `--no-remove`: аварийно останавливает операцию, если APT захочет удалить
|
||
пакет;
|
||
- `--force-confold`: сохраняет локальные конфиги вместо тихой замены;
|
||
- `NEEDRESTART_MODE=l`: показывает сервисы со старыми библиотеками, но не
|
||
перезапускает все сервисы автоматически.
|
||
|
||
Пакетные maintainer scripts все равно могут перезапустить собственный сервис.
|
||
Абсолютно гарантировать отсутствие краткого service interruption при системном
|
||
обновлении невозможно.
|
||
|
||
### 7. Не удаляет зависимости автоматически
|
||
|
||
По умолчанию выполняется только dry-run:
|
||
|
||
```bash
|
||
apt-get --dry-run autoremove
|
||
```
|
||
|
||
Кандидаты попадают в журнал. Реальный `autoremove` включается только вручную
|
||
через конфигурацию.
|
||
|
||
### 8. Не перезагружает сервер
|
||
|
||
Скрипт проверяет `/var/run/reboot-required` и сравнивает текущее ядро с
|
||
`/vmlinuz`. При необходимости пишет:
|
||
|
||
```text
|
||
REBOOT REQUIRED. Automatic reboot disabled.
|
||
```
|
||
|
||
Решение о reboot остается у администратора.
|
||
|
||
### 9. Показывает итог
|
||
|
||
В конце журнал содержит:
|
||
|
||
- failed systemd units;
|
||
- использование диска;
|
||
- необходимость reboot;
|
||
- успешные и неуспешные этапы.
|
||
|
||
## Настройка
|
||
|
||
Файл:
|
||
|
||
```bash
|
||
sudo nano /etc/default/safe-monthly-maintenance
|
||
```
|
||
|
||
Параметры:
|
||
|
||
| Параметр | По умолчанию | Значение |
|
||
|---|---:|---|
|
||
| `ENABLE_AUTOREMOVE` | `0` | `1` разрешает `apt-get autoremove --purge` |
|
||
| `ENABLE_DOCKER_PRUNE` | `0` | `1` удаляет только dangling Docker images |
|
||
| `JOURNAL_MAX_AGE` | `30d` | Максимальный возраст systemd journal |
|
||
| `JOURNAL_MAX_SIZE` | `500M` | Максимальный размер journal |
|
||
| `MIN_ROOT_FREE_KB` | `1048576` | Минимум свободного места на `/` |
|
||
| `MIN_BOOT_FREE_KB` | `204800` | Минимум на отдельном `/boot` |
|
||
|
||
Для серверов с важными stopped-контейнерами и локальными Docker-образами
|
||
оставляйте `ENABLE_DOCKER_PRUNE=0`.
|
||
|
||
## Управление
|
||
|
||
Следующий запуск:
|
||
|
||
```bash
|
||
systemctl list-timers safe-monthly-maintenance.timer --all
|
||
```
|
||
|
||
Запустить вручную:
|
||
|
||
```bash
|
||
sudo systemctl start safe-monthly-maintenance.service
|
||
```
|
||
|
||
Последний статус:
|
||
|
||
```bash
|
||
systemctl status safe-monthly-maintenance.service
|
||
```
|
||
|
||
Логи:
|
||
|
||
```bash
|
||
journalctl -u safe-monthly-maintenance.service
|
||
```
|
||
|
||
Логи текущего запуска:
|
||
|
||
```bash
|
||
journalctl -u safe-monthly-maintenance.service --since today
|
||
```
|
||
|
||
Отключить автоматический запуск:
|
||
|
||
```bash
|
||
sudo systemctl disable --now safe-monthly-maintenance.timer
|
||
```
|
||
|
||
Удалить:
|
||
|
||
```bash
|
||
sudo systemctl disable --now safe-monthly-maintenance.timer
|
||
sudo rm -f /etc/systemd/system/safe-monthly-maintenance.timer
|
||
sudo rm -f /etc/systemd/system/safe-monthly-maintenance.service
|
||
sudo rm -f /usr/local/sbin/safe-monthly-maintenance
|
||
sudo systemctl daemon-reload
|
||
```
|
||
|
||
Конфигурация и package snapshots при удалении сохраняются намеренно.
|
||
|
||
## Массовое развертывание
|
||
|
||
Пример с локальным списком серверов:
|
||
|
||
```bash
|
||
for host in vm1.example.com vm2.example.com vm3.example.com; do
|
||
ssh "$host" \
|
||
'curl -fsSL https://raw.githubusercontent.com/andrey271192/safe-monthly-maintenance/v1.0.2/install.sh | sudo bash -s -- --run-now'
|
||
done
|
||
```
|
||
|
||
Сначала используйте одну тестовую VM. Для большой инфраструктуры лучше Ansible,
|
||
Salt или другой configuration-management инструмент.
|
||
|
||
## Ограничения
|
||
|
||
- Скрипт не делает filesystem/provider snapshot.
|
||
- Скрипт не исправляет сломанный `dpkg` автоматически.
|
||
- Скрипт не обновляет Ubuntu/Debian между major releases.
|
||
- Скрипт не управляет сторонними package managers.
|
||
- Скрипт не гарантирует отсутствие service restart от maintainer scripts.
|
||
- Скрипт не заменяет мониторинг, резервные копии и тестирование обновлений.
|
||
|
||
Подробная модель безопасности: [docs/SAFETY.md](docs/SAFETY.md).
|
||
|
||
## Лицензия
|
||
|
||
[MIT](LICENSE)
|