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

28

Supposons que j'ai un script script.sh, qui prend un certain temps à 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?

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

Becko
la source
2
similaire à unix.stackexchange.com/q/121013/55673 sur U&L
Utilisateur enregistré

Réponses:

36

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

Ainsi, les modifications que vous apportez 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'effectuer ces modifications.

Cependant, lorsque vous exécutez à nouveau le script modifié sans mettre fin à l'instance précédemment exécutée, il y aura deux instances du script, l'une contenant les modifications et l'ancienne.

Soyez averti que les ressources que le script utilise et modifie entreront en conflit. Par exemple, si vous modifiez un fichier à l'aide du script, le script qui s'exécute ultérieurement ne pourra pas ouvrir ce fichier en écriture et ne pourra pas s'exécuter correctement.

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

En fonction de la taille du script et du compilateur / interprète en question, le script est chargé partiellement / complètement. Ainsi, si le script n'est pas complètement chargé, les modifications que vous apportez à votre script se répercuteront sur l'instance en cours d'exécution une fois la partie du script chargée en mémoire.

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

jobin
la source
11
Pas la réponse parfaite, lisez unix.stackexchange.com/q/121013/55673
Utilisateur enregistré le
@registereduser: oh oui, cette question m'a juste rappelé mes leçons d'OS. Éditera ma réponse dès que je mettrai la main sur mon bureau (sur mon téléphone en ce moment)
jobin
Je suppose que pour les scripts courts, il ne devrait pas y avoir de problème.
Becko
1
Lorsque j'ai essayé cela avec bash v3.2.48 (voir ici ), il n'a pas mis en mémoire tampon au-delà de la fin de la ligne (et a échoué mal lorsque j'ai modifié le script lors de son exécution). Je viens de retester avec bash v4.3.0, et il a tamponné le script (court) entier. Alors ... je ne compterais pas sur un comportement particulier.
Gordon Davisson
1
@RegisteredUser Pas avec toutes les versions de bash - voir l'exemple que j'ai lié.
Gordon Davisson
4

J'ajouterai quelque chose qui, je pense, n'a pas été dit dans les autres réponses. Tout dépend de la façon dont vous modifiez le fichier. Faire à echo "stuff" >filepartir du shell (une autre instance) va en effet écraser le fichier, je pense. Mais si vous modifiez le fichier avec par exemple emacs, puis enregistrez, cela ne se produira pas. Au lieu de cela, l'éditeur renomme l'ancien fichier en un nom de sauvegarde (peut-être en train de supprimer la sauvegarde précédente), puis écrit son contenu de tampon modifié 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 n'ouvrira presque certainement le fichier qu'une seule fois, il est par la suite indépendant du lieu où se trouve le nom du fichier, il continue simplement de lire le fichier du disque physique (identifié par le numéro d'inode) qui était associé au nom du fichier au moment de l'ouverture. Ainsi, même s'il lit le script par blocs (ce qui serait la solution la plus simple si vous utilisez des E / S de texte en mémoire tampon), il continuera à lire les lignes de l'ancienne instance du fichier, qui ne changera probablement pas lors de votre modification.

Marc van Leeuwen
la source
+1 J'utilise Sublime Text comme éditeur. Savez-vous s'il renomme aussi le fichier, comme emacs?
Becko
1
Je pense que la plupart des éditeurs utiliseraient un schéma de changement de nom (même s'ils ne devraient pas conserver les versions de sauvegarde) pour éviter le risque que si un plantage se produisait pendant le processus d'écriture, aucune version intacte du texte ne resterait du tout. Vous pouvez vérifier avec "ls -i" (qui affiche les numéros d'inode) quel est le comportement de votre éditeur.
Marc van Leeuwen
1

cela doit être mis à jour, les réponses ci-dessus ne sont désormais que partiellement correctes:

avec la version actuelle de bash, la modification d'un script sur le disque pendant son exécution obligera bash à "essayer" de charger les modifications en mémoire et de les reprendre dans le script en cours d'exécution. si vos modifications viennent après la ligne en cours d'exécution, les nouvelles lignes seront chargées et exécutées. mais, c'est une supposition par bash et cela peut faire le bien ou le mal.

la meilleure façon de procéder 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 du disque, la version mémoire perd ses liens avec elle de sorte que lorsque vous fournissez une nouvelle version à l'étape 3, aucune tentative par bash ne sera effectuée pour charger le nouveau contenu dans la version mémoire.

ivor
la source
0

La réponse de @ jobin est généralement correcte, mais j'ajouterai d'autres réponses qui peuvent être pertinentes selon ce que vous voulez faire.

Si vous voulez changer le script et que vous savez qu'il est sûr, alors vous voulez écrire dans un nouveau fichier, pas celui existant. Le nouveau fichier peut être localisé là où l'ancien était cependant. Écrivez votre nouvelle version dans un nouveau fichier, puis utilisez-la mvpour la mettre en place par-dessus l'ancienne. Le fichier qui a été remplacé existe toujours, il n'est tout simplement pas lié à partir du répertoire. Votre script en cours d'exécution peut continuer à l'utiliser, et lorsque ce script ferme son descripteur de fichier, 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 adopter le comportement du script à la volée, vous avez un problème plus difficile. Je suppose que vous auriez besoin de l'intégrer dans le code du script. Les scripts Bash peuvent gérer des signaux (par exemple, peuvent attraper quelque chose comme kill -USR1 [pid]), et un script peut alors répondre en rechargeant du code. Alors peut-être que vous pouvez obtenir des fonctionnalités proches 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 d'aussi complexe, vous voudrez probablement un plus sophistiqué langage de programmation pour le faire.

Si vous voulez pirater le comportement d'un script en cours d'exécution qui n'est pas écrit dans cet esprit, alors vous n'avez pas de chance. J'hésiterais à appeler toute tâche de programmation impossible, mais si vous aviez les ressources et les compétences pour ce genre de tâche, vous ne le demanderiez probablement pas ici.

mc0e
la source