Резервное копирование не идёт: хранилище копий заблокировано
Средства резервного копирования ставят блокировку на хранилище, чтобы два запуска не портили данные. Прерванный запуск блокировку не снимает, и следующие запуски падают. Опасность в том, что падает это тихо: таймер срабатывает, задача отказывает, копий нет неделями.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Блокировка осталась от прерванного запуска
Прошлая задача была убита по таймауту или вместе с сеансом. Блокировка в хранилище осталась.
-
Задача убивается по таймауту
Долгое копирование не успевает за отведённое время, systemd его убивает, и блокировка остаётся. Так повторяется каждый запуск.
-
Отказ таймера никто не замечает
Таймер срабатывает, задача падает, и об этом нет ни письма, ни оповещения. Отсутствие копий обнаруживается тогда, когда они нужны.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
История запусков: когда копирование удавалось в последний раз.
journalctl -u backup.service --since "14 days ago" --no-pager | grep -iE "Started|Failed|lock"Когда таймер срабатывал и когда сработает снова.
systemctl list-timers backup.timer --no-pagerТаймаут задачи и оповещение об отказе.
systemctl show backup.service -p TimeoutStartSec -p OnFailureРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Прошлая задача была убита по таймауту или вместе с сеансом. Блокировка в хранилище осталась.
- Как проверить
-
Посмотрите сообщение задачи и время последнего успешного запуска.
journalctl -u backup.service -n 30 --no-pager | grep -iE "lock|failed" systemctl show backup.service -p ExecMainExitTimestamp
- Как исправить
- Снимите блокировку штатной командой средства копирования, убедившись, что процесса копирования нет. Удалять файлы блокировки вручную не нужно.
- Почему происходит
- Долгое копирование не успевает за отведённое время, systemd его убивает, и блокировка остаётся. Так повторяется каждый запуск.
- Как проверить
-
Посмотрите таймаут и длительность прошлых запусков.
systemctl show backup.service -p TimeoutStartSec -p Type journalctl -u backup.service --since "7 days ago" --no-pager | grep -iE "Started|Succeeded|Failed|timeout"
- Как исправить
-
Увеличьте таймаут для задачи копирования или снимите его совсем: для одноразовой задачи с непредсказуемой длительностью это уместно.
[Service] Type=oneshot TimeoutStartSec=infinity
- Почему происходит
- Таймер срабатывает, задача падает, и об этом нет ни письма, ни оповещения. Отсутствие копий обнаруживается тогда, когда они нужны.
- Как проверить
-
Посмотрите, чем заканчивались последние запуски.
systemctl list-timers backup.timer --no-pager systemctl is-failed backup.service; systemctl show backup.service -p OnFailure
- Как исправить
-
Добавьте оповещение об отказе через
OnFailure=и следите за состоянием задачи снаружи. Таймер без наблюдения за результатом — источник ложного спокойствия.[Unit] OnFailure=notify-failure@%n.service
Пример вывода
Блокировка осталась от прерванного запуска. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
systemd[1]: Starting backup.service - Nightly backup...
borg[5400]: Failed to create/acquire the lock /srv/repo/lock.exclusive (timeout).
systemd[1]: backup.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
systemd[1]: backup.service: Failed with result 'exit-code'.
Связанные ошибки
- Таймер срабатывает, но задача падает незаметно Таймер работает исправно, а задача каждый раз завершается ошибкой, и об этом никто не узнаёт. Как настроить оповещение через OnFailure.
- Job for … failed because a timeout was exceeded Задание на запуск прервано по таймауту. Как отличить медленный старт от заблокированного и правильно настроить TimeoutStartSec.
- status=2/INVALIDARGUMENT в systemd Код 2/INVALIDARGUMENT: программа сочла аргументы или настройки недопустимыми. Частая причина — лишние кавычки в ExecStart=.
- Failed to parse calendar expression: ошибка в OnCalendar systemd не разбирает календарное выражение таймера. Правила записи OnCalendar и проверка через systemd-analyze calendar.
- clocksource: Marking clocksource unstable Ядро переключило источник времени. Службы видят скачки времени, таймеры срабатывают не тогда, когда ожидалось.
- status=212/TIMERSLACK в systemd Код 212/TIMERSLACK: не удалось задать допуск таймеров процесса из TimerSlackNSec=. Редкий код.
- Два таймера на одну службу: срабатывания накладываются Одна служба вызывается несколькими таймерами: запуски накладываются, часть срабатываний теряется.
- Периодическая очистка неиспользуемых блоков не работает Задача очистки блоков падает: файловая система или устройство не поддерживают операцию, либо путь смонтирован не так.
Источники
- Документация Borg: блокировки хранилища
-
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено убийством задачи копирования на середине.