42 votes

Puis-je modifier un script bash (.sh) pendant son exécution ?

Supposons que j'ai un script script.sh, qui prend du temps pour s'exécuter. Je l'exécute, ./script.sh. Pendant qu'il s'exécute dans une fenêtre de terminal, je modifie le fichier script.sh. Cela aura-t-il un effet sur le processus déjà en cours d'exécution?

Après l'avoir modifié, j'exécute le fichier modifié, donc j'ai maintenant deux processus en cours d'exécution. Est-ce que c'est correct?

47voto

jobin Points 25504

Lorsque vous apportez des modifications à votre script, vous les faites sur le disque (disque dur - le stockage permanent); lorsque vous exécutez le script, le script est chargé dans votre mémoire (RAM).

Donc, les modifications apportées au script n'affecteront pas le script en cours d'exécution, il exécutera la version que vous avez exécutée avant d'apporter ces modifications.

Cependant, lorsque vous exécutez à nouveau le script modifié sans terminer l'instance en cours d'exécution précédemment, il y aura deux instances du script - l'une avec les changements et l'ancienne.

Soyez averti que les ressources utilisées et modifiées par le script entreront en conflit. Par exemple, si vous modifiez un fichier en utilisant le script, le script qui s'exécute ensuite ne pourra pas ouvrir ce fichier en écriture et échouera à s'exécuter correctement.

Mise à jour: Merci à l'utilisateur enregistré de m'avoir dirigé vers une meilleure réponse sur Unix.stackexchange.com.

En fonction de la taille du script et du compilateur/interpréteur en question, le script est chargé partiellement/complètement. Ainsi, si le script n'est pas entièrement chargé, les modifications que vous apportez à votre script seront reflétées dans l'instance en cours d'exécution une fois que la partie du script est chargée en mémoire.

Il n'est donc pas recommandé de modifier votre script sur le disque qui est actuellement en cours d'exécution pour un résultat imprévisible : arrêtez d'abord l'instance en cours d'exécution, puis modifiez votre script et ensuite réexécutez le script.

9voto

ivor Points 91

Ceci doit être mis à jour, les réponses précédentes ne sont désormais que partiellement correctes:

avec la version actuelle de bash, modifier un script sur disque alors qu'il est en cours d'exécution amènera bash à "essayer" de charger les modifications en mémoire et à les prendre en compte dans le script en cours d'exécution. si vos modifications interviennent après la ligne actuellement exécutée, les nouvelles lignes seront chargées et exécutées. mais, c'est une supposition de la part de bash et cela peut être correct ou incorrect.

la meilleure façon de faire cela est la séquence d'actions suivante: 1) charger le script en mémoire 2) supprimer le script du disque 3) écrire un nouveau script sur le disque en supprimant d'abord la version sur disque, la version en mémoire perd ses liens avec elle, de sorte que lorsque vous fournissez une nouvelle version à l'étape 3, bash ne tentera pas de charger les nouveaux contenus dans la version en mémoire.

6voto

Marc van Leeuwen Points 201

Je vais ajouter quelque chose que je pense n'a pas été dit dans les autres réponses. Beaucoup dépend simplement de comment vous éditez le fichier. Faire echo "stuff" >file depuis le shell (une autre instance) écrasera en effet le fichier, je pense. Mais si vous éditez le fichier par exemple avec emacs et ensuite enregistrez, cela n'arrivera pas. Au lieu de cela, l'éditeur renommera l'ancien fichier en un nom de sauvegarde (peut-être en supprimant en fait la sauvegarde précédente), et ensuite écrira le contenu modifié de son tampon en tant que nouveau fichier avec l'ancien nom (maintenant libéré). Étant donné que le shell (ou un autre interpréteur) lisant le script ouvrira presque certainement le fichier une seule fois, il sera ensuite indépendant de l'emplacement du nom du fichier, il continuera simplement à lire le fichier disque physique (identifié par le numéro d'inode) qui était associé au nom du fichier au moment de l'ouverture. Donc même s'il lit le script par blocs (ce qui serait la solution la plus simple en utilisant une entrée/sortie texte mise en tampon), il continuera à lire les lignes de l'ancienne instance du fichier, qui est probablement inchangée par votre édition.

1voto

mc0e Points 309

La réponse de @jobin est généralement correcte, mais je vais ajouter quelques autres réponses qui pourraient être pertinentes en fonction de ce que vous voulez faire.

Si vous voulez modifier le script et que vous voulez savoir que c'est sûre, alors vous voulez écrire dans un nouveau fichier, pas dans l'existante. Le nouveau fichier peut être situé à l'endroit où se trouvait l'ancien. Écrivez votre nouvelle version dans un nouveau fichier, puis utilisez mv pour le déplacer en place par-dessus l'ancien. Le fichier qui a été remplacé existe toujours, il n'est simplement pas lié depuis le répertoire. Votre script en cours d'exécution peut continuer à l'utiliser, et lorsque ce script ferme son gestionnaire de fichiers, le système sait qu'il peut nettoyer le fichier en toute sécurité (que ce soit immédiatement ou ultérieurement).

Si vous voulez modifier le comportement du script en direct, vous avez un problème plus difficile. Je suppose que vous devrez l'intégrer dans le code du script. Les scripts Bash peuvent gérer les signaux (par exemple, peuvent attraper quelque chose comme kill -USR1 [pid]), et un script pourrait alors répondre en rechargeant une partie du code. Peut-être pouvez-vous obtenir une fonctionnalité proche de ce que vous voulez, mais sans savoir ce que vous recherchez, je ne vois pas de bonne raison de le faire, et je soupçonne que si vous voulez faire quelque chose de aussi complexe, vous voulez probablement utiliser un langage de programmation plus sophistiqué pour le faire.

Si vous voulez modifier le comportement d'un script en cours d'exécution qui n'a pas été écrit en gardant cela à l'esprit, alors vous êtes malchanceux. J'hésiterais à qualifier une tâche de programmation d'impossible, mais si vous aviez les ressources et les compétences pour ce type de tâche, vous ne seriez probablement pas en train de demander ici.

0voto

Martin Kealey Points 101

Le shell n'est pas comme les autres langages de script.

Le shell lit et exécute les commandes une par une, donc la réponse simple est "oui, modifier un script en cours d'exécution peut l'affecter", mais il est important de comprendre les détails.

Si vous faites attention, vous pouvez ajouter des lignes à la fin d'un script en cours d'exécution, et elles seront exécutées après les autres commandes déjà présentes dans le script.

echo "echo 'Cette commande supplémentaire sera également exécutée.'" >> votrescript.sh

Certains éditeurs peuvent écrire un nouveau fichier (inode) avec le même nom que l'ancien ; les modifications apportées de cette manière n'affecteront pas ce que le shell lit (c'est pourquoi ces éditeurs agissent ainsi). Cela complique donc certaines tentatives de test.

Mais tant que vous travaillez toujours avec le même inode, le shell en cours d'exécution sera affecté si le script est modifié au-delà du point où il a été lu - à moins bien sûr qu'il n'invoque exit avant cela.

La lecture est généralement effectuée par blocs de 4 Ko, de sorte que les petits scripts peuvent sembler s'exécuter sans être affectés, mais lorsqu'ils sont proches de la fin du fichier, le shell (comme tous les programmes de traitement de texte) lira tout ce qu'il peut obtenir. Cette "lecture partielle" ne signale pas en soi la fin du fichier, et le shell continuera à lire jusqu'à ce qu'il ne lise aucun octet. Ainsi, si le fichier s'allonge pendant que le shell le lit, le shell lira les nouvelles données.

Il est important de noter à ce stade que le shell ne tentera pas de lire plus de données tant qu'il n'en aura pas besoin, que ce soit pour terminer d'analyser une commande composée, ou parce qu'il a simplement exécuté toutes les commandes précédentes. Ce délai est l'occasion de modifier le fichier contenant le script.

Donc tout changement qui rendra le fichier plus long aura presque toujours un effet.

Modifier un fichier et insérer N octets au milieu repositionnera les derniers N octets du fichier juste après l'ancienne fin du fichier. Ces octets seront lus comme "nouveaux" par le shell, même s'il les a juste lus à leur position précédente.

Et pour compliquer les choses davantage, comme les limites de bloc et de ligne ne coïncideront probablement pas, le shell peut commencer à lire à mi-chemin à travers une ligne, donnant lieu à l'effet de "charabia". Cela peut se produire si vous ajoutez ou supprimez des lignes qui se trouvent avant la position jusqu'à laquelle le shell a lu.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X