launchd startInterval меньше времени, необходимого для завершения сценария


2

Я использую launchctl для загрузки / запуска моего скрипта Python, и он работает в определенной степени. Он запускается каждые 120 секунд, но иногда мой сценарий запускается за 500 секунд, и моя теория заключается в том, что у меня запущен процесс, который перезапускает его, а не позволяет запустить первый.

Я думаю, что происходит: - запустить tester.py (примерное время tester.py завершить 400 с) - через 120 с - снова запустить tester.py и отказаться от первого

Что я хочу: чтобы закончить первый tester.py, не перезапускать его.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>BuildNotification.py</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python</string>
        <string>/Users/xcuer/tester.py</string>
    </array>
    <key>StartInterval</key>
    <integer>120</integer>
    <key>TimeOut</key>
    <integer>7200</integer>
    <key>ExitTimeOut</key>
    <integer>7200</integer>
</dict>
</plist>

Я пытаюсь придумать хорошее решение, кроме проверки сценария на наличие предыдущих вызовов и выхода ...
bmike

@bmike Я пытаюсь понять, решает ли crontab эту проблему
donttellunclesam,

1
Файл блокировки был бы традиционным решением для этой ситуации. Вы можете изменить скрипт?
Грэм Милн

@GrahamMiln Как будет работать файл блокировки для моего решения? Или есть способ, которым я мог бы написать сценарий bash, который вызывает launchctl вместо самого сценария python? Есть ли в laucnhctl способ проверить, работает ли служба в данный момент?
donttellunclesam

1
Я использовал @GrahamMiln предложенный ответ crontabи launchdрабочие места. Его тест на 4 строки в оболочке может быть очень легко написан на Python, Perl, AppleScript или любом другом языке сценариев.
дан

Ответы:


1

launchd фокусируется на запуске заданий и поддержании их выполнения, в нем нет механизма для обработки перекрывающихся заданий.

Блокировка файла

Традиционно в среде UNIX файл блокировки используется для остановки многократного запуска процессов.

Основные шаги:

  1. При запуске скрипта, если файл блокировки уже существует, остановите скрипт.
  2. При запуске скрипта, если файл блокировки не существует, создайте файл блокировки.
  3. По завершении сценария удалите файл блокировки.

В macOS создайте файл блокировки /var/tmpдля общесистемных процессов.

Пример реализации

if ! mkdir /var/tmp/myscript.lock 2>/dev/null; then
    echo "Myscript is already running." >&2
    exit 1
fi

См. Быстрый и грязный способ убедиться, что одновременно выполняется только один экземпляр сценария оболочки, и Каков наилучший способ убедиться, что запущен только один экземпляр сценария Bash? для примеров сценариев.

Потенциальные проблемы

Есть крайние случаи.

launchdхочет, чтобы задания выполнялись как минимум за n секунд до окончания . Когда сценарий найдет существующий файл блокировки, подумайте о том, чтобы поспать в течение n секунд, а затем выйти.

Что произойдет, если ваш скрипт будет убит или завершится из-за ошибки? Можете ли вы быть уверены, что файл блокировки удален?

В Си хитрость, гарантирующая удаление файла, заключается в создании, открытии и удалении файла - удаленный файл, оставшийся открытым в UNIX, останется до завершения процесса открытия. Файл удаляется даже в случае сбоя процесса.

В сценарии оболочки перехватите сигнал завершения и убедитесь, что файл удален.

Другая потенциальная проблема - проверка на наличие файла. Эта проверка может произойти за доли секунды до завершения предыдущего скрипта. Это будет редко, но возможно. Приведенный выше подход претендует на преодоление этого.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.