Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

la vie d'un script Bash ?

14 réponses
Avatar
Thierry B.
Bonsoir.

Question existentialiste: durée de vie d'un script shell.

J'explique:
J'écris un shell un peu tortueux, qui appelle pas mal de
commandes externes, et s'exécute en deux ou trois semaines.

Je le lance, et il se déroule. Il grinke, il grinke, et moi,
je vais dormir. Le lendemain, je me réveille avec une idée
de modif. A ce moment, puis-je considérer que le bash qui
exécute le script déja lancé en a conservé la totalité,
et que je peux modifier le fichier script sans porter
préjudice à ce qui se déroule déja ?

La question porte d'abord sur:
"GNU bash, version 3.00.16(1)-release (i486-pc-linux-gnu)"
mais si vos bienveillantes réponses pouvaient être plus
générales, j'en serais ravi.


--
"Forty-two!"
"Is that all you've got to show for seven and a half million years of work?"
"I checked it very thoroughly", said the computer...

10 réponses

1 2
Avatar
Luc.Habert.00__arjf
"Thierry B." :

Je le lance, et il se déroule. Il grinke, il grinke, et moi,
je vais dormir. Le lendemain, je me réveille avec une idée
de modif. A ce moment, puis-je considérer que le bash qui
exécute le script déja lancé en a conservé la totalité,
et que je peux modifier le fichier script sans porter
préjudice à ce qui se déroule déja ?


Je ne sais pas pour ton shell précis, mais je crois avoir déjà eu des ennuis
en faisant ça.

Avatar
Cyrille Lefevre
Je le lance, et il se déroule. Il grinke, il grinke, et moi,
je vais dormir. Le lendemain, je me réveille avec une idée
de modif. A ce moment, puis-je considérer que le bash qui
exécute le script déja lancé en a conservé la totalité,
et que je peux modifier le fichier script sans porter
préjudice à ce qui se déroule déja ?


en un mot, non, en ksh/posix shell tout du moins.
en ce qui concerne bash, aucune idée.

un moyen de contournement simple, les fonctions.

au lien de faire :

#!/usr/bin/sh
script complet

fait :

#!/usr/bin/sh
foo() { ... }
bar() { ... }
foobar() { foo; bar; }
main() { while getopts, etc.; foobar; }
main ${1+"$@"}

comme cela, ton shell n'a pas a reprendre la relecture du script
après l'exécution d'une commande puisque tout est en fonctions.

alternative, source :

#!/usr/bin/sh
. /path/to/foo
. /path/to/bar
. /path/to/foobar

ce qui implique de ne pas modifier le script principale (caller),
mais autorise de modifier les scrips appelés (callee) puisqu'ils
ne sont sourcés qu'au moment ou ils ont besoin d'être exécutés.

perso, je combine les 2, les source au debut qui définissent des
fonctions, puis j'utilise les fonctions. alternative, les autoloads
en ksh implémentable en bash.

Regards, Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.
remove "%nospam" and ".invalid" to answer me.

Avatar
Thierry B.
--{ Cyrille Lefevre a plopé ceci: }--

Je le lance, et il se déroule. Il grinke, il grinke, et moi,
je vais dormir. Le lendemain, je me réveille avec une idée


un moyen de contournement simple, les fonctions.

[...]


perso, je combine les 2, les source au debut qui définissent des
fonctions, puis j'utilise les fonctions. alternative, les autoloads
en ksh implémentable en bash.


Ouaou, je suis impressioné ! Merci pour toutes ces pistes,
qui vont me donner les moyens d'enhancer ma productivity.


--
_____________________________________________________________________
= = = = = = = = = = = = = = = = = = = = = = = = = = = = Kikooooooooo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Avatar
Daniel Déchelotte
"Thierry B." :

Je le lance, et il se déroule. Il grinke, il grinke, et moi,
je vais dormir. Le lendemain, je me réveille avec une idée
de modif. A ce moment, puis-je considérer que le bash qui
exécute le script déja lancé en a conservé la totalité,
et que je peux modifier le fichier script sans porter
préjudice à ce qui se déroule déja ?


Je ne sais pas pour ton shell précis, mais je crois avoir déjà eu des
ennuis en faisant ça.


Et de mon coté je suis sur que ça m'a déjà posé problème (avec bash).
En fait, j'en suis arrivé à la conclusion que l'interpréteur est
feignant : il ne lit que ce dont il a besoin, peut-etre par blocs de n
(4096 ?) octets. Quand il avance, il lit la suite du script « à la
demande ». Si le fichier a grossi ou rétréci entre temps, c'est le
drame.

Ce qui marche, c'est de modifier le fichier _en s'assurant de ne pas
décaler les caractères_. Par exemple, si tu as un « sleep 300 » que tu
veux modifier en 30, mets un espace avant ou après le 30 pour avoir le
meme nombre de caractères que 300. :)

Plus propre, j'ai pris l'habitude de copier le script dans le répertoire
dans lequel il produit ses résultats, et de le relancer là-bas.

C'est peut-etre pas clair. Voici le fragment de code (tcsh !) :

set wdir=blabla # C'est là que je mets les « produits »
mkdir -p $wdir # Je le crée au cas où
set avant=`pwd`
pushd $wdir # J'y vais
set apres=`pwd`
popd # Je reviens (pour pouvoir utiliser $0...)
if ( $avant != $apres ) then # Si premier lancement :
cp -f $0 $wdir # je recopie le script
chmod 544 $wdir/`basename $0`
cd $wdir
echo Relaunching there.
exec ./`basename $0` # et je le relance du nouveau rep
else
echo Now here. Keeping going. # Deuxieme lancement : au boulot !
endif

--
Daniel Déchelotte
http://yo.dan.free.fr/


Avatar
Stephane Chazelas
2007-07-26, 17:58(+02), Daniel Déchelotte:
[...]
Et de mon coté je suis sur que ça m'a déjà posé problème (avec bash).
En fait, j'en suis arrivé à la conclusion que l'interpréteur est
feignant : il ne lit que ce dont il a besoin, peut-etre par blocs de n
(4096 ?) octets. Quand il avance, il lit la suite du script « à la
demande ». Si le fichier a grossi ou rétréci entre temps, c'est le
drame.
[...]


Au contraire, l'interpreteur est tres zélé.

Le shell se comporte de la meme facon quand il lit ses
intructions depuis l'utilisateurs et quand il les lit depuis un
fichier ou une socket ou un pipe et fait tres attention de ne
pas lire plus que necessaire.

Quand bash lit plus que necessaire (en faisant un read(buf,
BUFFLEN) pour optimisation parce qu'il sait que le code vient
d'un fichier regulier) qui va plus loin que la ligne courante,
il fait un lseek en arriere pour etre sur que le prochain read
lira la ligne suivante.

Ce n'est pas une limitation, c'est une feature.

--
Stéphane

Avatar
Pascal Bourguignon
Daniel Déchelotte writes:
Plus propre, j'ai pris l'habitude de copier le script dans le répertoire
dans lequel il produit ses résultats, et de le relancer là-bas.


Mais c'est quand même plus simple de mettre le script dans une fonction.

#!/bin/bash
main () {
...
}
main "$@"

--
__Pascal Bourguignon__ http://www.informatimago.com/

ATTENTION: Despite any other listing of product contents found
herein, the consumer is advised that, in actuality, this product
consists of 99.9999999999% empty space.

Avatar
Stephane Chazelas
2007-07-26, 18:51(+02), Pascal Bourguignon:
Daniel Déchelotte writes:
Plus propre, j'ai pris l'habitude de copier le script dans le répertoire
dans lequel il produit ses résultats, et de le relancer là-bas.


Mais c'est quand même plus simple de mettre le script dans une fonction.

#!/bin/bash
main () {
...
}
main "$@"


Note que

#!/bin/bash
{
...
}

suffit.

Par exemple, observer ce que se passe quand on tape ca au
prompt, le shell ne fait rien tant qu'on n'a pas entré la "}"
fermante.

--
Stéphane


Avatar
Thierry B.
--{ Stephane Chazelas a plopé ceci: }--

Quand bash lit plus que necessaire (en faisant un read(buf,
BUFFLEN) pour optimisation parce qu'il sait que le code vient
d'un fichier regulier) qui va plus loin que la ligne courante,
il fait un lseek en arriere pour etre sur que le prochain read
lira la ligne suivante.

Ce n'est pas une limitation, c'est une feature.

Je me doutais d'un truc dans ce genre, mais je n'avais pas

pensé à la ruse du lseek... Maintenant, il me reste à trouver
une méthode pour contourner la feature...


--
Imaginez votre dilemne si en regardant 2 jolies capture d'écran on vous
disait : Alors, "XP vs VISTA", que choisissez vous ?

Avatar
Luc.Habert.00__arjf
"Thierry B." :

Maintenant, il me reste à trouver une méthode pour contourner la
feature...


Il suffit de ne pas enregistrer la nouvelle version du script dans le même
fichier. J'ignore quel éditeur tu utilises, en tout cas c'est ce qu'Emacs
fait par défaut : quand on lui demande d'enregistrer, il renome l'ancienne
version, et écrit la nouvelle dans un nouveau fichier (portant le même nom,
mais ce n'est plus le même fichier).

(Ou alors il fait un truc un peu plus compliqué (création d'un deuxième lien
dur plutôt que renomage, création de la nouvelle version sous un nom
temporaire, puis renomage une fois qu'elle est remplie) pour que le
remplacement soit atomique, j'ai la flemme de vérifier.)

Avatar
Daniel Déchelotte

Il suffit de ne pas enregistrer la nouvelle version du script dans le
même fichier. J'ignore quel éditeur tu utilises, en tout cas c'est ce
qu'Emacs fait par défaut : quand on lui demande d'enregistrer, il
renome l'ancienne version, et écrit la nouvelle dans un nouveau
fichier (portant le même nom, mais ce n'est plus le même fichier).


Apparemment, il ne fait ça qu'à la première sauvegarde. Les sauvegardes
suivantes (pour une meme session d'Emacs) utilisent la meme inode. Et
lorsqu'on quitte et relance Emacs, on risque de retrouver... l'inode
initiale. (c'est sans doute pour ça qu'il ne change pas d'inode à chaque
sauvegarde successive).

--
Daniel Déchelotte
qui aime bien la solution « { list; } »

1 2