web-dev-qa-db-fra.com

Comment créer un travail Upstart à exécution unique dont l'exécution est garantie avant le début de deux autres travaux?

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.

5
froage

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.

3
froage

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.

2
Lety
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é.

1
CameronNemo