Можно ли запускать программы чаще, чем каждые 10 секунд?

8

У меня есть некоторые подобные сервисы, которые я хотел бы запустить почти сразу после изменения файлов.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>test</string>
    <key>ProgramArguments</key>
    <array>     
        <string>say</string>
        <string>a</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/Users/username/Desktop/</string>
    </array>
</dict>
</plist>

Даже если для ThrottleInterval задано значение 1 или 0, они запускаются не чаще, чем каждые 10 секунд.

9/9/12 4:57:05.457 PM com.apple.launchd.peruser.501[138]: (test) Throttling respawn: Will start in 7 seconds
9/9/12 4:57:09.541 PM com.apple.launchd.peruser.501[138]: (test) Throttling respawn: Will start in 3 seconds

man launchd.plist только говорит, что программы запускаются не чаще, чем каждые 10 секунд по умолчанию, но не упоминает, что ThrottleInterval не может быть установлен ниже этого.

ThrottleInterval <integer>
This key lets one override the default throttling policy imposed on jobs by launchd.
The value is in seconds, and by default, jobs will not be spawned more than once
every 10 seconds.  The principle behind this is that jobs should linger around just
in case they are needed again in the near future. This not only reduces the latency
of responses, but it encourages developers to amortize the cost of program invoca-
tion.

Вы можете оставить программу или скрипт на 10 секунд и следить за изменениями каждую секунду:

#!/bin/bash

start=$(date +%s)
prev=

until (( $(date +%s) >= $start + 10 )); do
    new=$(stat -f %m ~/Desktop/)
    [[ $prev != $new ]] && say a
    prev=$new
    sleep 1
done

Или то же самое в Ruby:

#!/usr/bin/env ruby

start = Time.now
prev = nil

until Time.now >= start + 10
  current = File.mtime("#{ENV['HOME']}/Desktop/")
  `say a` if current != prev
  prev = current
  sleep 1
end

Но есть ли способ обойти или уменьшить ограничение по времени? Это также относится к действиям папки.

LRI
источник

Ответы:

9

Невозможно обойти или уменьшить ограничение по времени.

Документация Apple по созданию Launchd Jobs гласит следующее:

Важно Если ваш демон завершает работу слишком быстро после запуска, launchd может подумать, что он вышел из строя. Демоны, которые продолжают это поведение, могут быть приостановлены и больше не запускаться при поступлении будущих запросов. Чтобы избежать этого, не выключайте компьютер в течение 10 секунд после запуска.

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

Кроме того, вы можете просматривать определенные файлы с помощью API kqueue или FSEvents. Этот вопрос StackOverflow может быть полезным, на уровне файлов уведомлений об изменениях в файловой системе Mac OS X .

Грэм Милн
источник
2

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

Затем запустите ваш скрипт каждые x минут на случай, если предыдущий прогон прекратится. Кодируйте начало вашего скрипта, чтобы проверить, запущен ли другой экземпляр, и если да, выйдите из него.

Бессонница программного обеспечения
источник
Не похоже, что launchd запускает другой экземпляр, если предыдущий все еще работает.
Lri
launchd не будет запускать несколько экземпляров одного и того же задания.
Грэм Милн
1

Если вам нужно запускать скрипт чаще, чем каждые 10 секунд, он может быть дорогостоящим с точки зрения «разветвления» (читай: выделение памяти, запуск новых процессов и т. Д.).

Поэтому в этом случае лучше всего написать собственный « демон » (программа, которая работает в фоновом режиме)

Я рекомендую вам использовать «более способный» язык в качестве BASH (мой любимый - «perl», но ruby ​​тоже в порядке), потому что хороший демон обрабатывает тайм-ауты, аварийные сигналы и т. Д. - вещи, которые слишком сложно реализовать в чистом bash. (Конечно, демон может запускать ваши bash-скрипты - при необходимости). Основы:

  • скрипт, который работает бесконечно и ждет какого-то события. Событие может быть каким-то сетевым входом или простым таймером или чем-то подобным. Когда приходит событие (например, состояние ожидания закончилось), скрипт будет делать то, что вы хотите, и цикл повторяется.

В мире perl уже существуют модули, которые настраивают ваш скрипт как процесс «демон», например, Proc :: Daemon . У меня нет опыта работы с ruby, но эта статья может вам помочь.

Вы можете запустить процесс демона через Launchd при запуске системы, либо из приложения automator при входе в систему, либо из терминала вручную.

jm666
источник