mirror of
https://github.com/andrey271192/safe-monthly-maintenance.git
synced 2026-09-21 12:01:57 +00:00
Add safe monthly maintenance installer
This commit is contained in:
298
README.md
Normal file
298
README.md
Normal file
@@ -0,0 +1,298 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user