web-dev-qa-db-fra.com

Modifier le script Shell pendant son exécution

Pouvez-vous éditer un script Shell pendant son exécution et que les modifications affectent le script en cours d'exécution?

Je suis curieux de savoir le cas particulier d'un script csh dont le lot exécute différentes versions et qui fonctionne toute la nuit. Si quelque chose m'arrive en cours d'opération, j'aimerais ajouter des commandes supplémentaires ou commenter celles qui n'ont pas été exécutées.

Si ce n’est pas possible, existe-t-il un mécanisme Shell ou batch qui me permettrait de le faire?

Bien sûr, j'ai essayé, mais il faudra des heures avant de voir si cela a fonctionné ou non, et je suis curieux de savoir ce qui se passe ou non dans les coulisses.

69
ack

[edit] Voir aussi cette réponse, section pour contourner le problème.

Cela affecte , du moins bash dans mon environnement, mais de manière très désagréable . Voir ces codes. Premier a.sh:

#!/bin/sh

echo "First echo"
read y

echo "$y"

echo "That's all."

b.sh:

#!/bin/sh

echo "First echo"
read y

echo "Inserted"

echo "$y"

# echo "That's all."

Faire

$ cp a.sh run.sh
$ ./run.sh
$ # open another terminal
$ cp b.sh run.sh  # while 'read' is in effect
$ # Then type "hello."

Dans mon cas, le résultat est toujours:

bonjour 
 bonjour 
 C'est tout. 
 C'est tout.

C'est imprévisible, donc dangereux. Voir cette réponse, section pour des solutions de contournement.

[ajouté] Le comportement exact dépend d'une nouvelle ligne, et peut-être aussi de votre style Unix, de votre système de fichiers, etc. Si vous voulez simplement voir certaines influences, ajoutez simplement "echo foo/bar" à b.sh avant et/ou après la ligne "read".

44
teika kazura

Essayez ceci ... créez un fichier appelé "bash-is-odd.sh":

#!/bin/bash
echo "echo yes i do odd things" >> bash-is-odd.sh

Cela démontre que bash interprète effectivement le script "au fur et à mesure". En effet, l'édition d'un script long a des résultats imprévisibles: insertion de caractères aléatoires, etc. Pourquoi? Parce que bash lit à partir de la dernière position d’octet, l’édition modifie l’emplacement du caractère en cours de lecture.

Bash est, dans un mot, très, très dangereux à cause de cette "fonctionnalité". svn et rsync, lorsqu'ils sont utilisés avec des scripts bash, sont particulièrement troublants car, par défaut, ils "fusionnent" les résultats ... en cours d'édition. rsync a un mode qui résout ce problème. svn et git ne le font pas.

Je présente une solution. Créez un fichier appelé "/ bin/bashx":

#!/bin/bash
source "$1"

Maintenant, utilisez #!/Bin/bashx sur vos scripts et exécutez-les toujours avec "bashx" au lieu de bash. Cela corrige le problème - vous pouvez rsynciser vos scripts en toute sécurité.

Solution alternative (en ligne) proposée/testée par @ AF7:

{
   # your script
} 
exit $?

Les accolades protègent contre les modifications et la sortie protège contre les ajouts. Bien sûr, nous serions tous mieux lotis si bash proposait une option, telle que '-w' (fichier complet), ou quelque chose qui l'ait fait.

31
Erik Aronesty

Divisez votre script en fonctions et chaque fois qu'une fonction s'appelle vous source depuis un fichier séparé. Vous pouvez ensuite modifier les fichiers à tout moment et votre script en cours enregistrera les modifications lors de la prochaine acquisition.

foo() {
  source foo.sh
}
foo
15
glenn jackman

Si tout cela est dans un seul script, alors non, cela ne fonctionnera pas. Toutefois, si vous le configurez en tant que script de pilote appelant des sous-scripts, vous pourrez peut-être modifier un sous-script avant son appel ou avant de le rappeler si vous faites une boucle. serait reflété dans l'exécution.

1
Ethan Shepherd

Bonne question! J'espère que ce script simple vous aidera

#!/bin/sh
echo "Waiting..."
echo "echo \"Success! Edits to a .sh while it executes do affect the executing script! I added this line to myself during execution\"  " >> ${0}
sleep 5
echo "When I was run, this was the last line"

Sous Linux, il semble que les modifications apportées à un fichier .sh en cours d’exécution soient exécutées par le script d’exécution, si vous pouvez taper assez vite!

1
Will Turner

Je n'ai pas installé csh, mais

#!/bin/sh
echo Waiting...
sleep 60
echo Change didn't happen

Exécutez cela, éditez rapidement la dernière ligne à lire

echo Change happened

La sortie est

Waiting...
/home/dave/tmp/change.sh: 4: Syntax error: Unterminated quoted string

Hrmph.

Je suppose que les modifications apportées aux scripts Shell ne prennent effet que lorsqu'elles sont réexécutées.

1
dave4420

Je n'entends pas ... mais qu'en est-il avec une certaine indirection:

BatchRunner.sh

Command1.sh
Command2.sh

Command1.sh

runSomething

Command2.sh

runSomethingElse

Ensuite, vous devriez pouvoir éditer le contenu de chaque fichier de commande avant que BatchRunner ne l’ait bien compris?

OU

Dans une version plus propre, BatchRunner regarderait un fichier unique dans lequel il exécuterait consécutivement une ligne à la fois. Ensuite, vous devriez pouvoir éditer ce deuxième fichier pendant que le premier fonctionne correctement?

0
ack

Remarque intéressante: si vous exécutez un script Python, il ne change pas. (Ceci est probablement évident pour quiconque comprend comment Shell exécute les scripts Python, mais pense que cela pourrait être un rappel utile pour ceux qui recherchent cette fonctionnalité.)

J'ai crée:

#!/usr/bin/env python3
import time
print('Starts')
time.sleep(10)
print('Finishes unchanged')

Ensuite, dans un autre shell, pendant qu'il est en veille, modifiez la dernière ligne. Une fois cette opération terminée, la ligne non modifiée s'affiche, probablement parce qu'il exécute un .pyc? Il en va de même sur Ubuntu et MacOS.

0
Chris