10 votes

Est-ce que launchd peut exécuter des programmes plus fréquemment que toutes les 10 secondes ?

J'ai quelques services de ce type que j'aimerais exécuter presque immédiatement après la modification des fichiers.

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

Même si ThrottleInterval était réglé sur 1 ou 0, ils ne sont exécutés au maximum que toutes les 10 secondes.

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 indique seulement que les programmes ne sont pas exécutés plus de toutes les 10 secondes par défaut, mais ne mentionne pas que ThrottleInterval ne peut pas être défini en dessous de cela.

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.

Vous pourriez laisser le programme ou le script fonctionner pendant 10 secondes et observer les changements chaque seconde :

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

Ou la même chose 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

Mais existe-t-il un moyen de contourner ou de diminuer la limite de temps ? Cela s'applique également aux actions sur les dossiers.

10voto

Graham Miln Points 39606

Il n'y a aucun moyen de contourner ou de diminuer la limite de temps.

La documentation d'Apple concernant Création d'emplois Launchd déclare ce qui suit :

Important Si votre démon s'arrête trop rapidement après avoir été lancé, launchd peut penser qu'il s'est écrasé. Les démons qui continuent ce comportement peuvent être suspendus et ne pas être relancés lors de futures requêtes arrivent. Pour éviter ce comportement, ne vous arrêtez pas pendant au moins 10 minutes. secondes après le lancement.

Votre programme ou script doit continuer à fonctionner pendant au moins 10 secondes. Envisagez d'implémenter une boucle pour vérifier les dates de modification des fichiers dans les dix dernières secondes, de dormir pendant dix secondes, et de répéter.

Vous pouvez également surveiller des fichiers spécifiques à l'aide de la commande kqueue ou les API FSEvents. Cette question de StackOverflow peut être utile, Notification des modifications du système de fichiers au niveau des fichiers dans Mac OS X .

2voto

Insomniac Software Points 1843

Vous pourriez laisser votre script tourner en boucle pour vérifier les fichiers modifiés au lieu de quitter lorsqu'il a terminé. Faites-le dormir pendant quelques secondes après avoir vérifié les fichiers modifiés. S'il trouve des fichiers modifiés, continuez avec le script. Si ce n'est pas le cas, faites-le dormir à nouveau.

Ensuite, demandez à launchd de lancer votre script toutes les x minutes juste au cas où l'exécution précédente meurt. Codez le début de votre script pour vérifier si une autre instance est déjà en cours d'exécution et si c'est le cas, se quitter.

0 votes

Launchd ne semble pas démarrer une autre instance si la précédente est toujours en cours.

0 votes

Launchd ne lancera pas plusieurs instances du même ticket de travail.

1voto

jm666 Points 7802

Si vous devez lancer un script plus souvent que toutes les 10 secondes, cela peut s'avérer coûteux en termes de "forking" (lire : allocation de mémoire, lancement de nouveaux processus etc).

Par conséquent, dans ce cas, le mieux est d'écrire votre propre " démon "(programme, ce qui fonctionne en arrière-plan)

Je vous recommande d'utiliser un langage "plus capable" que BASH (mon préféré est "perl", mais ruby est OK aussi) parce qu'un bon démon gère les timeouts, les alarmes et ainsi de suite - des choses qui sont trop difficiles à implémenter en bash pur. (Bien sûr, le daemon peut exécuter vos scripts bash aussi - si nécessaire). Les bases sont les suivantes :

  • script qui tourne sans fin et attend un événement. L'événement peut être une entrée réseau, un simple timer ou autre. Quand l'événement arrive (par exemple la fin de l'état d'attente) le script fera ce que vous voulez et le cycle se répète.

Dans le monde perl, il existe déjà des modules qui font de votre script un processus "démon", par exemple Proc::Daemon . Je ne suis pas expérimenté avec ruby, mais cet article peut vous aider.

Vous pouvez lancer votre processus démon via Launchd au démarrage du système, ou à partir de l'application Automator lorsque vous vous connectez, ou encore manuellement à partir du terminal.

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X