@Lelouch

Как не дать скрипту выполняться, если другая его копия уже запущена?

Я написал скрипт на Python, который ищет в определенной папке CSV файлы и если находит их, то производит над данными некоторые преобразования, а затем загружает их в MySQL, откуда я уже могу забирать данные в BI и работать с ними.

Сейчас я хочу немного автоматизировать процесс и доработав скрипт добавить его в crontab, чтобы просто закинув файлы в нужную папку самостоятельно (или каким то еще скриптом) я был уверен что все обработается нормально и данные попадут в БД.

Но, я не очень представляю себе как именно Python и Linux работают с файлами. Файлы могут быть очень большими и скрипт может выполняться вплоть до десятков минут. При этот ставить в crontab выполнение раз в несколько часов не хотелось бы.

Я планирую сделать такую логику скрипта:
1. Смотрим сколько файлов в папке и берем первый.
2. Разбиваем его на части и забираем в датафрейм панд первую часть.
3. Удаляем эту часть из файла (если строки кончились, удаляем сам файл).
4. Производим нужные манипуляции с данными и отправляем их БД.
5. exit()

И соответственно ставим все это чудо в crontab запускаться каждую минуту.

Вопрос в том будет ли все это нормально работать или нужно делать как-то по другому? Возможны ли при такой логике следующие ситуации и как их лучше избежать:
1. Crontab запустил первую копию скрипта, она выполняется, и в момент записи обновленной версии файла, из которого убрали ту часть данных, с которой сейчас работаем, crontab запускает вторую копию скрипта, которая заберет неполный файл?
2. По каким-то причинам сервер будет загружен и скрипт не будет успевать за минуту обработать ожидаемый объем, в результате я через пару часов получу около сотни одновременно работающих копий которые все повесят?
  • Вопрос задан
  • 223 просмотра
Решения вопроса 1
Adamos
@Adamos
Если существует файл /tmp/ваш_скрипт.lock - завершить работу.
Создать файл /tmp/ваш_скрипт.lock
Выполнить работу.
Удалить файл /tmp/ваш_скрипт.lock

Подвох: если ваш скрипт упал, не дойдя до последнего пункта - больше он не запустится. Так что на п. 1 стоит предусмотреть - "если файл существует и моложе 10 минут", например.
Ответ написан
Пригласить эксперта
Ответы на вопрос 5
sergey-gornostaev
@sergey-gornostaev Куратор тега Python
Седой и строгий
При запуске проверять наличие pid-файла в /var/run. Если файл есть сразу завершать работу. Если нет, то создавать, регистрировать atexit-обработчик для его удаления и выполнять основную работу.
Ответ написан
Melkij
@Melkij
PostgreSQL DBA
flock -n путь_к_lock_файлу команда_запуска_вашего_скрипта

Что есть вариация других опубликованных здесь ответов, но зато при сбое по какой-либо причине скрипт всё-таки будет запущен в следующий раз и не будет ждать пока вы сами удалите оставшийся lock файл.
Ответ написан
@Ddeeeennn
Как вариант - создать хендл write для файла. Если первый скрипт создал, то второй уже не сможет.
Ответ написан
alekciy
@alekciy
Вёбных дел мастер
Самый нормальный гарантированный вариант - использование мьютекса через IPC семафоры ОС (для linux).
Ответ написан
saboteur_kiev
@saboteur_kiev Куратор тега Linux
build engineer
Стандартное решение в Линукс - это создание PIDFILE с номером выполняющегося процесса.
При запуске скрипта, проверяется файл, проверяется что процесс который в нем указан запущен. Если запущен - значит завершить работу, чтобы не мешать уже выполняющемуся.
Если не запущен - первым делом создать PIDFILE.
В конце скрипта удалить за собой PIDFILE.

Можно поискать в питоне готовую библиотеку, посмотреть как с ней работать
import pidfile
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы