¿Se pueden ejecutar y ejecutar programas con más frecuencia que cada 10 segundos?

8

Tengo algunos servicios como este que me gustaría ejecutar casi inmediatamente después de modificar los archivos.

<?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>

Incluso si ThrottleInterval se estableció en 1 o 0, solo se ejecutan cada 10 segundos como máximo.

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 solo dice que los programas no se ejecutan más de cada 10 segundos de forma predeterminada, pero no menciona que ThrottleInterval no se pudo establecer debajo de eso.

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.

Puede mantener el programa o el script en ejecución durante 10 segundos y observar los cambios cada segundo:

#!/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

O lo mismo en 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

¿Pero hay alguna manera de evitar o disminuir el límite de tiempo? También se aplica a las acciones de carpeta.

    
pregunta user495470 09.09.2012 - 16:23

3 respuestas

9

No hay manera de evitar o disminuir el límite de tiempo.

La documentación de Apple relativa a Creación de trabajos de Launchd indica la siguiente:

  

Importante Si su demonio se apaga demasiado rápido después de ser lanzado, Launchd puede pensar que se ha estrellado. Demonios que continúan esto.   El comportamiento puede suspenderse y no volver a iniciarse cuando futuras solicitudes   llegar. Para evitar este comportamiento, no apague por lo menos 10   segundos después del lanzamiento.

Su programa o script debe seguir ejecutándose durante al menos 10 segundos. Considere la posibilidad de implementar un bucle para verificar las fechas de modificación de archivos en los últimos diez segundos, dormir diez segundos y repetir.

Alternativamente, puedes ver archivos específicos usando kqueue o FSEvents APIs. Esta pregunta de StackOverflow puede ser útil, notificación de cambio de sistema de archivos a nivel de archivo en Mac OS X .

    
respondido por el Graham Miln 11.09.2012 - 12:38
2

Podría mantener su secuencia de comandos ejecutándose en un bucle buscando archivos modificados en lugar de salir cuando se haya terminado. Hágalo dormir por unos segundos después de verificar los archivos modificados. Si encuentra archivos modificados, continúe con el script. Si no, vuelve a dormir.

Luego, inicie e inicie su secuencia de comandos cada x minutos, en caso de que la ejecución anterior muera. Codifique el principio de su script para verificar si otra instancia ya se está ejecutando y, de ser así, salga de sí mismo.

    
respondido por el Insomniac Software 11.09.2012 - 10:17
1

Si necesita iniciar un script con más frecuencia que cada 10 segundos, puede ser costoso en términos de "bifurcación" (lea: asignar memoria, iniciar nuevos procesos, etc.).

Por lo tanto, en este caso, lo mejor es escribir su propio " daemon " (programa, ¿qué corre en el fondo)

Te recomiendo que uses un lenguaje "más capaz" como BASH (mi favorito es "perl", pero ruby también está bien) porque un buen daemon maneja los tiempos de espera, las alarmas, etc., lo que es demasiado difícil de implementar en bash puro . (Por supuesto, el demonio también puede ejecutar sus scripts de bash, si es necesario). Los conceptos básicos son:

  • secuencia de comandos lo que se ejecuta sin fin y esperando algún evento. El evento puede ser una entrada de red, un temporizador simple o algo parecido. Cuando llegue el evento (por ejemplo, el estado de espera finalizado), el script hará lo que quieras y el ciclo se repetirá.

En el mundo Perl ya existen módulos que optimizan su script como proceso "daemon", por ejemplo Proc :: Daemon . No tengo experiencia con ruby, pero este artículo puede ayudarlo.

Puede iniciar el proceso de su daemon a través de Launchd en el inicio del sistema, o desde la aplicación automator al iniciar sesión, o desde la Terminal manualmente.

    
respondido por el jm666 11.09.2012 - 19:57

Lea otras preguntas en las etiquetas