Comment peut-on écrire une tâche Upstart dont l'exécution est garantie ne seule fois après chaque démarrage, mais dont l'exécution est également garantie avant que l'un au moins des deux autres travaux ne commence à s'exécuter. Je ne souhaite pas modifier les fichiers d'initialisation Upstart pour ces deux autres travaux, car ils ne m'appartiennent pas. Le redémarrage de l’un ou l’autre de ces deux autres travaux ne doit pas entraîner la réexécution de la tâche souhaitée.
La situation est que la tâche souhaitée doit apporter certaines modifications à certains fichiers du système de fichiers local dont les deux autres travaux auront besoin.
Upstart est un nouveau venu et je trouve que la courbe d’apprentissage est plus raide que prévu; une formation sur pourquoi la solution fonctionnera sera aussi utile que la solution elle-même.
Je pense avoir une réponse à ma propre question qui exploite solution partielle de CameronNemo et réponse de Mark Russell à une question connexe mais quelque peu différente.
Deux fichiers de configuration Upstart sont requis. Le premier est un travail qui commence dès que le système de fichiers local est disponible, effectue les modifications de fichier souhaitées en tant que script de pré-démarrage, puis reste inactif à l'état en cours d'exécution:
# modify-files - Single-execution file modification job
start on local-filesystems
console log
pre-start script
echo "$(date --rfc-3339=ns) $(hostname) $UPSTART_JOB"
exec /path/to/your/script
end script
Le deuxième fichier de configuration est une tâche Upstart qui retarde le démarrage de tous les autres travaux susceptibles de dépendre des fichiers que nous essayons de modifier. Il produit une instance de lui-même par travail dépendant:
# modify-files-wait - Helper task for modify-files
start on (starting jobA or jobB)
stop on (started modify-files or stopped modify-files)
instance $JOB
console log
normal exit 0 2
task
script
echo "$(date --rfc-3339=ns) $(hostname) $UPSTART_JOB ($UPSTART_INSTANCE)"
status modify-files | grep -q "start/running" && exit 0
start modify-files || true
sleep infinity
end script
Upstart va tuer toutes les instances de modify-files-wait
une fois que modify-files
est inactif dans son état en cours d'exécution. Cette ligne normal exit
indique la possibilité d'être tué pendant son sommeil infini. Nous avons besoin de la ligne task
pour bloquer jobA et joB jusqu'à ce que l'état d'arrêt soit atteint. Quelle que soit l'instance exécutée en premier, modify-files
démarrera, si elle n'a pas déjà été démarrée.
Étant donné que modify-files
n'atteint jamais l'état arrêté, il ne sera jamais exécuté à nouveau, que le travail A ou le travail B soit redémarré.
Cette solution semble fonctionner, mais toute critique ou amélioration est la bienvenue.
Vous pouvez définir un travail de tâche simple commençant par l'événement de votre choix, exécuter votre script et, à la fin, émettre un événement pour démarrer les deux autres travaux.
Par exemple:
# mainJob -
#
# This service emit myEvent to run firstJob
description "emit myEvent to run firstJob"
start on runlevel [2345]
task
console log
script
echo "(startTask) $UPSTART_JOB -- $UPSTART_EVENTS"
exec /path/to/your/script
initctl emit -n myEvent
end script
Afin de ne pas modifier le script de démarrage des deux autres travaux, vous devez remplacer les fichiers qui vous permettent de modifier le chemin dans lequel un travail commence et s’arrête en modifiant les conditions de démarrage et d’arrêt.
En suivant mes exemples, j'ai créé un simple firstJob.conf
comme ceci:
# firstJob -
#
# This service print environment variable
description "print environment variable"
start on runlevel [2345]
stop on runlevel [016]
task
console log
script
if [ "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" -o "$RUNLEVEL" = "6" ]; then
exec echo "(stopTask) $UPSTART_JOB -- $UPSTART_EVENTS"
else
exec echo "(startTask) $UPSTART_JOB -- $UPSTART_EVENTS"
fi
end script
Et ensuite, je remplace le démarrage à la condition que le fichier de substitution soit créé:
echo "start on myEvent" > /etc/init/firstJob.override
Donc, firstJob
démarrera sur myEvent
généré par mainJob
et s’arrêtera sur runlevel [016]
J'ai testé ces travaux sur lubuntu 12.04 et après le redémarrage, j'ai trouvé dans /var/log/upstart/firstJob.log
:
(startTask) firstJob -- myEvent
Vous devez vérifier si "les deux autres travaux" nécessitent une condition d'événement particulière pour démarrer et vous assurer que mainJob
démarre sur ces événements.
start on starting jobA or starting jobB
instance $JOB
pre-start exec /path/to/script
Le bit de démarrage empêche les travaux d'avancer dans leur cycle de vie jusqu'à la fin de ce travail.
Le bit d'instance est tel que les deux événements de départ (pour jobA et jobB) sont inhibés, pas un seul, comme ce serait le cas si vous n'aviez pas de strophe d'instance.
L’utilisation de exec/script pré-démarrage (à la place d’un exec/script normal) est telle que, lorsque la commande script/execute est terminée, le travail est toujours considéré comme en cours d’exécution, alors qu’avec un exec/script traditionnel, le travail est considéré être arrêté lorsque l'exec/script se termine.
Utiliser tâche serait précisément ce qui fait que le travail est exécuté deux fois (par exemple, si les travaux que vous avez redémarrés), nous le laissons donc de côté.