Вопрос или проблема
Я хочу сделать автоматическое резервное копирование на флешку после её автоматического монтирования.
Для этого я написал в /etc/fstab…
UUID=0698-A3CF /flash vfat noauto,nofail,x-systemd.automount,x-systemd.idle-timeout=15,x-systemd.device-timeout=15
А в /etc/systemd/system/ я создал юнит my_backup.service. Я заполнил его согласно этим инструкциям.
[Unit]
Description=Триггер моего резервного скрипта
Requires=flash.automount
After=flash.automount
[Service]
ExecStart=/myfolder/python_backup.py
[Install]
WantedBy=flash.automount
Скрипт на Python отлично работает, если я запускаю его отдельно, и почти идеально, если я запускаю его при монтировании флешки. Почти, за исключением… фактического копирования необходимых файлов. В журнале написано “Нет устройства /flash”. Кроме того, раскоментив функции для работы с файлами, используя задержку в скрипте на Python и команду ls /flash, я выяснил, что флешка не монтируется до завершения работы скрипта. Но в юните написано “After”! Можно ли переписать юнит так, чтобы скрипт на Python начинал выполняться после монтирования флешки?
Ответ или решение
После выполнения автоматического монтирования флеш-накопителя возникла проблема с запуском вашего скрипта для резервного копирования. Давайте подробно разберем причины этого и предложим возможные решения.
Проблема: Синхронизация между монтированием и выполнением скрипта
Ваши наблюдения о том, что скрипт выполняется до завершения монтирования, указывают на то, что система не ждет окончания процесса монтирования, прежде чем начнет запускать команду ExecStart
в вашем unit-файле. Хотя вы указали директиву After=flash.automount
, это не гарантирует, что монтирование завершится к тому времени, как скрипт начнет выполняться. Директива After
управляет порядком запуска, но не создает зависимости на уровне завершенности операций.
Почему это происходит?
Когда вы запускаете резервное копирование, служба systemd не может обнаружить флеш-накопитель, так как он еще не был полностью смонтирован, что вызывает ошибку "No /flash device".
Решения
1. Изменение зависимостей в unit-файле
Попробуем изменить конфигурацию вашего unit-файла. Вместо того чтобы полагаться только на After
, добавьте также BindsTo
для создания жесткой зависимости от автоматического монтирования:
[Unit]
Description=My backup script trigger
Requires=flash.automount
After=flash.automount
BindsTo=flash.automount
[Service]
Type=oneshot
ExecStart=/myfolder/python_backup.py
[Install]
WantedBy=flash.automount
Здесь Type=oneshot
указывает, что сервис завершится после выполнения, и эта настройка может помочь системе ожидать завершения монтирования.
2. Использование дополнительных системных таймеров
Если указание After
и BindsTo
не решает проблему, вы можете рассмотреть использование системного таймера для отложенного запуска скрипта. Это позволит дать больше времени для монтирования перед запуском скрипта. Вам нужно создать отдельный unit-файл для таймера.
Создайте файл /etc/systemd/system/my_backup.timer
:
[Unit]
Description=Timer for my backup script
[Timer]
OnActiveSec=15s
Unit=my_backup.service
[Install]
WantedBy=timers.target
Обратите внимание, что здесь OnActiveSec=15s
устанавливает задержку на 15 секунд (вы можете регулировать значение в зависимости от необходимости).
3. Проверка наличия устройства в скрипте
Если проблема сохраняется, можно также ввести в ваш Python-скрипт проверку на доступность директории, которая будет срабатывать до завершения его основного кода. Это должно помочь избежать ошибок, если папка еще не смонтирована:
import os
import time
# Путь к монтированной папке
mount_point = '/flash'
# Проверка доступа к папке
while not os.path.ismount(mount_point):
print("Ожидание монтирования устройства...")
time.sleep(1)
# Продолжение выполнения копирования
Заключение
Необходимо помнить, что автоматизированное монтирование и выполнение операций с дисками требует четкого синхронизации процессов. Приведенные изменения должны помочь вам гарантировать, что флеш-накопитель будет смонтирован до того момента, как начнется выполнение вашего скрипта резервного копирования. Обязательно протестируйте изменения и при необходимости настройте задержки или дополнительные проверки в зависимости от оборудования.