0 votes

Exécuter script de manière atomique

J'ai une tâche launchd qui exécute un bash script périodiquement, et cela fonctionne très bien. Cependant, si je modifie le script pendant que la tâche est en cours d'exécution, soit en l'éditant directement, soit en le remplaçant par une copie mise à jour, cela peut amener la tâche en cours d'exécution à cracher une charge d'erreurs de syntaxe ou pire, à avoir un comportement imprévisible.

Le problème semble être qu'au lieu de charger le script en mémoire, ou de maintenir ouvert le fichier tel qu'il était au moment de l'exécution, launchd (ou probablement bash lui-même) charge le fichier en direct ligne par ligne, ce qui signifie que toute modification du script semble être reflétée en temps réel, ce qui entraîne des erreurs.

Pour tenter d'illustrer le problème, considérons l'exemple suivant :

if [ "$foo" = '1' ]; then
    do_something_that_takes_time
fi

Maintenant, imaginez que le script s'exécute à la ligne 2 ( do_something_that_takes_time ) et j'échange le script, en supprimant l'élément if/fi bloquer entièrement. Quand le script passe à la ligne 3, il ne trouvera plus de fi et continuera à exécuter en s'attendant à trouver une solution. fi mais ne le fera jamais, ce qui entraînera une erreur éventuelle (fin de fichier inattendue). Il peut aussi finir par sauter des commandes (qui ont été déplacées vers le haut suite à la suppression de lignes).

Bien sûr, je peux éviter ce problème en déchargeant la tâche launchd, en la mettant à jour, puis en la rechargeant, mais ce n'est pas très pratique, surtout pour les tâches qui peuvent prendre beaucoup de temps à se terminer (je préférerais les laisser se terminer, mais il ne semble pas y avoir de moyen de le faire et d'échanger le fichier à ce moment-là). Sinon, je dois ajouter un mécanisme pour empêcher la tâche de se relancer, afin que je puisse échanger le nouveau script à mon gré, mais cela semble être une étape supplémentaire inutile alors que Bash devrait simplement exécuter le script que je lui ai dit de faire, au moment où il a commencé.

Ma question est donc la suivante : existe-t-il un moyen de forcer launchd (ou Bash) à exécuter le script uniquement tel qu'il était au début de la tâche ? Par exemple en le chargeant entièrement en mémoire avant de l'exécuter, ou en le chargeant à partir d'un file-handle ouvert qui ne changera pas ?

Je poste ceci ici parce que je ne suis pas tout à fait sûr si c'est une bizarrerie de Bash en général, ou si c'est potentiellement spécifique à Mac d'une certaine manière. Le volume sur lequel je m'exécute utilise APFS, et devrait donc être copié sur l'écriture, donc je ne m'attendrais pas à ce que ce comportement se produise (car un handle de fichier ouvert devrait continuer à pointer sur l'ancien fichier, en ignorant les modifications apportées).

1voto

Douglas Points 10417

Ma question est donc la suivante : existe-t-il un moyen de forcer launchd (ou bash) à exécuter le script uniquement tel qu'il était au début de la tâche ?

Non. Ce n'est pas une bizarrerie de bash ou de launchd . launchd charge le travail (plist) en mémoire, pas le script. Le script est appelé par sa définition de "start" comme RunAtLoad o CalendarInterval .

Aussi, la nuance ici est quand la tâche a commencé . Cela dépend du moment où la tâche a été configurée pour être lancée. Ce n'est pas parce que la définition de la tâche est chargée que la tâche a démarré.

Si vous définissez le travail sur la définition du poste en utilisant Program y ProgramArguments il peut théoriquement, faire ce que vous voulez. Cependant, il n'y a pas de logique script ; c'est juste une commande et ses arguments.

Maintenant, si votre script prend du temps ou pour le dire autrement, il est toujours en cours d'exécution si vous le modifiez, cela entraînera bien sûr des erreurs. Ce serait comme si vous exécutiez votre script, puis simultanément dans une autre session bash le modifier. Il y aura des problèmes.

launchd exécute simplement le script comme vous le feriez si vous tapiez la commande manuellement.

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