Таймер не начнёт копию, пока идёт прежняя: второй systemctl start дожидается конца первого запуска. Руками же скрипт можно запустить в любой момент.
Настоящая копия большого каталога идёт долго — в backup.sh её изображает sleep 3. Пусть ночью коллега запустил копию руками, пока работала служба. Повтори это одной строкой: & запускает первую команду в фоне, вторая начинается сразу, а wait дожидается фоновой.
Запусти две копии разом
В ~/sched-lab запусти backup.sh дважды одной строкой — первый в фоне, — а потом посмотри, что лежит в archive.
Сначала предположи
Сколько архивов окажется в archive после двух запусков?
Теперь начни упражнение, выполни команду и сверь прогноз с выводом.
Оба запуска упаковали data в один временный файл archive/partial.tar.gz. Первый переименовал его в архив, а второй файла уже не нашёл — отсюда mv: cannot stat. Будь упаковка длиннее, второй запуск ещё и переписал бы файл первому на середине.
Две копии разводит блокировка. flock держит блокировку файла, пока работает команда: flock -n /run/lock/backup.lock ./backup.sh запускает скрипт, если блокировка свободна, а если занята — сразу выходит с кодом 1. Ключ -n — не ждать; без него вторая копия дождётся первой и тоже отработает. В каталог /run/lock может писать любой пользователь, он и нужен для файлов блокировки.
Чтобы блокировку брал сам скрипт — и в службе, и при ручном запуске, — его ставят в начале скрипта:
exec 9>файл открывает файл как поток 9 на всё время работы скрипта — так же, как открыты потоки 1 и 2. flock -n 9 берёт блокировку на этот поток. Снимать её не нужно: он освобождается сам, когда скрипт завершается.