Discussion:
Lancer un script shell linux lors de la fermeture du terminal, avec la croix
(trop ancien pour répondre)
G2PC
2018-02-18 12:10:01 UTC
Permalink
Comment lancer un script shell linux lors de la fermeture du terminal,
avec la croix. ... ?

J'ai vu sur un forum qu'il serrait question d'utiliser SIGHUP.

Je n'ai pas réussi à reproduire l'exemple proposé. ( appel de fonction
"a" qui écrit correctement dans un fichier de logs , trap "a" )


J'aimerais pouvoir déclancher la suppression d'un dossier, si
l'utilisateur de quitte pas mon script avec la commande EXIT du menu que
j'ai créé.
Étienne Mollier
2018-02-18 18:40:02 UTC
Permalink
Bonjour,
Post by G2PC
Comment lancer un script shell linux lors de la fermeture du
terminal, avec la croix. ... ?
On peut potentiellement déjà avoir des problèmes dépendant de la
façon dont le gestionnaire de fenêtre utilisé ferme les fenêtres
avec la croix, s'il y a une croix... :-)

Normalement, tous le font de manières à laisser le temps à
l'application d'exécuter des tâches de nettoyage avant de
quitter, mais on peut avoir des surprises, en particulier si un
signal SIGKILL, qui ne peut de toute façon pas être trap'é, est
lancé trop tôt...
Post by G2PC
J'ai vu sur un forum qu'il serrait question d'utiliser SIGHUP.
Je n'ai pas réussi à reproduire l'exemple proposé. ( appel de
fonction "a" qui écrit correctement dans un fichier de logs ,
trap "a" )
Effectivement d'après le manuel signal(7) ça aurait pu avoir du
sens :

Signal Value Action Comment
──────────────────────────────────────────────────────────────────────
SIGHUP 1 Term Hangup detected on controlling terminal
or death of controlling process

Mais à l'usage, ça ne passe pas. Il me semble que ce signal est
plutôt utilisé pour recharger la configuration des dæmons sans
avoir à les redémarrer, ou ce genre de chose, désormais.

Il pourrait néanmoins y avoir une solution. Si le shell utilisé
est bash, alors il est possible de spécifier un pseudo signal
EXIT à la commande trap (pas SIGEXIT, ce n'est pas un signal
inter processus à proprement parler). Le code suivant permet par
exemple d'enregistrer la dernière fermeture de shell (testé avec
le gestionnaire dwm en faisant l'équivalent d'un clic sur une
hypothétique croix) :

last-exit () {
printf '%s\n' "$(date --rfc-2822)" > ~/.lastexit
}
trap last-exit EXIT

L'explication détaillée à propos de EXIT (et de quelque signaux
bonus) est disponible dans le manuel de bash, ou bien en sortie
de la commande :

$ help trap
trap: trap [-lp] [[arg] signal_spec ...]
Trap signals and other events.

Defines and activates handlers to be run when the shell receives signals
or other conditions.
[...]
If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell. If
[...]


Ça marche avec le bash de Debian Sid, je n'ai pas testé avec les
autres niveaux de Debian, donc je ne saurais dire si c'est une
solution éprouvée ou bien si c'est une nouveauté. :-)


Une autre solution exploitant le fichier ~/.bash_logout aurait pu
être envisagée mais suppose que la fenêtre de terminal a été
lancée avec `bash -l` et non `bash` tout court, qui est une
commande par défaut usuelle. De plus, le nettoyage
s'appliquerait à toute session utilisateur, et pas seulement dans
le contexte de votre script.
Post by G2PC
J'aimerais pouvoir déclancher la suppression d'un dossier, si
l'utilisateur de quitte pas mon script avec la commande EXIT du
menu que j'ai créé.
Juste pour éviter les cafouillages, le EXIT que je mentionne est
une entité différente du EXIT de votre menu.

Soyez prudents avec les situations de concurrence également.
Qu'est ce qui se passe quand un terminal dans un autre contexte
est fermé avec la croix ? Est ce que ça va déclencher le script
de nettoyage ? Est ce bienvenu ? Et si le programme tourne dans
d'autres terminaux, comment se comporte le nettoyage ?...


À plus,
--
Étienne Mollier <***@mailoo.org>
G2PC
2018-02-18 19:00:01 UTC
Permalink
Post by Étienne Mollier
last-exit () {
printf '%s\n' "$(date --rfc-2822)" > ~/.lastexit
}
trap last-exit EXIT
Bonsoir, et, merci pour le retour.
J'ai testé sur ma VM, mais, sans succès.

Oui, si je lance le script, un fichier est créé, contenant la date.
Non, le fichier n'est pas créé lorsque je quitte le terminal avec la
croix. J'ai tenté de le fermer au bout d'une minute, mais, la date est
ajoutée dans le fichier texte au lancement du script, pas à la fermeture
de la fenêtre.

Si le script ne fini pas normalement, ce n'est pas trop grâve, un
dossier installeur restera présent dans le répertoire utilisateur.
J'ai pu lire d'avantage, sur mktemp :
https://www.visionduweb.eu/wiki/index.php?title=Programmation_en_Shell_Bash_Linux#Cr.C3.A9er_un_fichier_temporaire_avec_mktemp
C'est une solution intéressante !

Malgré tout, ma question reste posée, avec un exemple, si il est
possible de lancer un script au moment de la fermeture d'un terminal,
avec la croix.
C'est surement inutile, puisque d'autres possibilités comme mktemp sont
adaptées.
Étienne Mollier
2018-02-18 20:20:02 UTC
Permalink
Post by G2PC
Oui, si je lance le script, un fichier est créé, contenant la
date. Non, le fichier n'est pas créé lorsque je quitte le
terminal avec la croix. J'ai tenté de le fermer au bout d'une
minute, mais, la date est ajoutée dans le fichier texte au
lancement du script, pas à la fermeture de la fenêtre.
De ce que vous décrivez, la fonction rattachée à l'évènement
s'exécuterait donc dès la déclaration de la fonction ; il y a
peut-être un bug dans votre essai.

Voici un script qui m'a permis de faire des tests plus poussés
pour simuler un installateur classique :

#!/bin/bash
set -e
set -v

# Creating an installation directory with a unique name,
# to avoid concurrency issues.
INSTALLDIR="$(mktemp -d installdir.XXXXXX)"

# Setting up cleanup of the installation directory on
# exit. WARNING: do not use `cd` in the script, as
# INSTALLDIR is a relative path.
clean-installdir () {
rm -r "$INSTALLDIR"
}
trap clean-installdir EXIT

# Installing...
printf "Installation in progress in %s\n" "$INSTALLDIR"
# The sleeping simulates the time it would take for a
# real installation to occur. You can close the program
# in any way you wish, to do some tests, in this time
# frame.
sleep 10

# Everything went well for the script
printf "%s\n" "Done."

# Note that you should see execution of clean-installdir
# here, as the program is exiting. :-)

Si je ferme le programme à coup de <C-c>, ou si je clos la
fenêtre avec le raccourci clavier de mon gestionnaire de fenêtre,
le répertoire d'installation est effacé. Si je laisse le
programme s'exécuter jusqu'au bout, c'est aussi le cas /sans/
appeler explicitement la fonction ; ce qui, soit dit en passant,
est cool.

Si je ferme la fenêtre de mon terminal avec le programme xkill,
le script reçoit un signal KILL impossible à capter. Par
conséquent, le répertoire d'installation reste présent à côté du
script, et doit être effacé manuellement. Il se peut que
certains gestionnaires de fenêtres aient ce genre de comportement
pour lutter contre les fenêtres récalcitrantes. Je n'ai testé
que dwm de mon côté, mais il y en a d'autres : xfwm4, metacity,
kwin, awesome, fvwm, openbox, et j'en passe.
Post by G2PC
Si le script ne fini pas normalement, ce n'est pas trop grâve,
un dossier installeur restera présent dans le répertoire
https://www.visionduweb.eu/wiki/index.php?title=Programmation_en_Shell_Bash_Linux#Cr.C3.A9er_un_fichier_temporaire_avec_mktemp
C'est une solution intéressante !
Malgré tout, ma question reste posée, avec un exemple, si il est
possible de lancer un script au moment de la fermeture d'un
terminal, avec la croix.
C'est surement inutile, puisque d'autres possibilités comme
mktemp sont adaptées.
Gardez la commande mktemp en tête, elle ne remplace pas le mécano
avec trap, mais elle participe à régler les problèmes de
concurrence mentionnés dans mon précédent courriel.


À plus,
--
Étienne Mollier <***@mailoo.org>
G2PC
2018-02-18 20:50:01 UTC
Permalink
Post by Étienne Mollier
Post by G2PC
Oui, si je lance le script, un fichier est créé, contenant la
date. Non, le fichier n'est pas créé lorsque je quitte le
terminal avec la croix. J'ai tenté de le fermer au bout d'une
minute, mais, la date est ajoutée dans le fichier texte au
lancement du script, pas à la fermeture de la fenêtre.
De ce que vous décrivez, la fonction rattachée à l'évènement
s'exécuterait donc dès la déclaration de la fonction ; il y a
peut-être un bug dans votre essai.
Voici un script qui m'a permis de faire des tests plus poussés
#!/bin/bash
set -e
set -v
# Creating an installation directory with a unique name,
# to avoid concurrency issues.
INSTALLDIR="$(mktemp -d installdir.XXXXXX)"
# Setting up cleanup of the installation directory on
# exit. WARNING: do not use `cd` in the script, as
# INSTALLDIR is a relative path.
clean-installdir () {
rm -r "$INSTALLDIR"
}
trap clean-installdir EXIT
# Installing...
printf "Installation in progress in %s\n" "$INSTALLDIR"
# The sleeping simulates the time it would take for a
# real installation to occur. You can close the program
# in any way you wish, to do some tests, in this time
# frame.
sleep 10
# Everything went well for the script
printf "%s\n" "Done."
# Note that you should see execution of clean-installdir
# here, as the program is exiting. :-)
Si je ferme le programme à coup de <C-c>, ou si je clos la
fenêtre avec le raccourci clavier de mon gestionnaire de fenêtre,
le répertoire d'installation est effacé. Si je laisse le
programme s'exécuter jusqu'au bout, c'est aussi le cas /sans/
appeler explicitement la fonction ; ce qui, soit dit en passant,
est cool.
Si je ferme la fenêtre de mon terminal avec le programme xkill,
le script reçoit un signal KILL impossible à capter. Par
conséquent, le répertoire d'installation reste présent à côté du
script, et doit être effacé manuellement. Il se peut que
certains gestionnaires de fenêtres aient ce genre de comportement
pour lutter contre les fenêtres récalcitrantes. Je n'ai testé
que dwm de mon côté, mais il y en a d'autres : xfwm4, metacity,
kwin, awesome, fvwm, openbox, et j'en passe.
Post by G2PC
Si le script ne fini pas normalement, ce n'est pas trop grâve,
un dossier installeur restera présent dans le répertoire
https://www.visionduweb.eu/wiki/index.php?title=Programmation_en_Shell_Bash_Linux#Cr.C3.A9er_un_fichier_temporaire_avec_mktemp
C'est une solution intéressante !
Malgré tout, ma question reste posée, avec un exemple, si il est
possible de lancer un script au moment de la fermeture d'un
terminal, avec la croix.
C'est surement inutile, puisque d'autres possibilités comme
mktemp sont adaptées.
Gardez la commande mktemp en tête, elle ne remplace pas le mécano
avec trap, mais elle participe à régler les problèmes de
concurrence mentionnés dans mon précédent courriel.
À plus,
Ici, effectivement, le fichier va être nettoyé automatiquement à la fin
de l'installation, ou, immédiatement, quand je ferme le terminal avec la
croix.
C'est tout à fait ce que j'attendais comme retour, et, oui, ça
fonctionne plutôt bien.

Noter que, il faut bien lancer le script en bash, avec sh, ça ne
fonctionnera pas.

Je note également que certains tueurs de programmes pourront empêcher le
bon fonctionnement du script, si trap n'est pas appelé normalement.

Bonne soirée, bonne fin de week end.
Merci beaucoup pour l'exemple.
Raphaël POITEVIN
2018-02-20 17:50:02 UTC
Permalink
Post by G2PC
Comment lancer un script shell linux lors de la fermeture du terminal,
avec la croix. ... ?
L’appeler dans .bash_logout ?
--
Raphaël
Étienne Mollier
2018-02-21 18:30:01 UTC
Permalink
Post by Raphaël POITEVIN
Post by G2PC
Comment lancer un script shell linux lors de la fermeture du terminal,
avec la croix. ... ?
L’appeler dans .bash_logout ?
Bonsoir,

L'approche est intéressante, mais ne marcherait pas dans le cas
concernant les terminaux quittés via la croix pour deux raisons.
La première est que la plupart des terminaux ne lancent pas par
défaut des shells de login, et la seconde est que, dans le cas
d'une utilisation dans un script de login, le .bash_logout n'est
appelé qu'a l'appel de la commande « exit ».

Ceci dit, c'était bien pensé. :-)

La section « INVOCATION » du manuel de Bash est assez détaillée
à ce sujet :

When an interactive login shell exits, or a non-interac‐
tive login shell executes the exit builtin command, bash
reads and executes commands from the file
~/.bash_logout, if it exists.


Il est toujours intéressant de noter que les terminaux des
divers environnements de bureau peuvent être configurés pour
être des shells de login via une option à cocher dans les
préférences. Pour le terminal XTerm, vous pouvez le lancer avec
l'option -ls.

La morale de cette histoire est que, c'est mal de fermer ses
terminaux avec la croix : si un programme en cours d'exécution
avait eu besoin de faire du ménage, il y a de grandes chances
pour qu'il faille repasser derrière faire le ménage à la mimine.
Gérer ce cas proprement au sein des programmes n'est pas simple.

À plus,
--
Étienne Mollier <***@mailoo.org>
Basile Starynkevitch
2018-02-21 19:00:02 UTC
Permalink
Post by Raphaël POITEVIN
Post by G2PC
Comment lancer un script shell linux lors de la fermeture du terminal,
avec la croix. ... ?
L’appeler dans .bash_logout ?
Moi j'aimerais comprendre pourquoi on veut faire ça. Je n'en vois pas la
raison. Un emulateur de terminal peut
disparaître à tout moment (par exemple avec xkill), indépendamment du
shell (ou du programme) qui y est executé.

Une possibilité (peut-être) serait de choisir puis configurer un window
manager convenable pour ça.

A mon avis la question initiale est une instance de problème XY
http://xyproblem.info/ et mériterait une motivation poussée.

Librement
--
Basile STARYNKEVITCH == http://starynkevitch.net/Basile
opinions are mine only - les opinions sont seulement miennes
Bourg La Reine, France
Loading...