Léa-Linux & amis :   LinuxFR   GCU-Squad   GNU
utilisation de 'trap'
Envoyé par: |/|BaH

Bonjour,

et re-bonjour à ceux qui ont suivi depuis mon précédent sujet : "un chronomètre en shell script".

Il s'avère que lors de l'éxécution de ce script, qui consiste en une boucle infinie, la commande 'trap' n'effectue pas l'action pour laquelle elle est prévue : intercepter une combinaison de touches et accomplir une commande ou une fonction stipulée entre

Je m'explique :
Le but du jeu est d'obtenir, lors de l'interruption du script par Ctrl-C, le rafraîchissement complet de la console.
[^]Plus tard on peut même imaginer que d'autres combinaisons de touches effectuent d'autres actions : suspension/reprise, initialisation, ... enfin! les différentes fonctions d'un chronomètre.[/^]
Alors,
soit je n'insère pas 'trap' : le script est interrompu par Ctrl-C, mais il n'y a pas de rafraîchissement
soit j'insère :
sortie(){
tput init; clear; break > /dev/null 2>&1 # *
}
trap 'sortie' 2

# * j'ai essayé avec 'exit', le comportement est identique,
#+ mais je n'aime pas être déloggué à la fin d'un script,
#+ je ne m'en sers donc que très parcimonieusement.
au tout début du script (j'ai aussi essayé de le mettre dans la boucle), et le script ne s'intrrompt pas; à moins d'appuyer sur la combinaison de touches Ctrl-C pendant plus d'une seconde.

Est-ce un comportement normal de 'trap' pour les scripts ne comportant qu'une boucle infinie ?

Poste le Tuesday 19 February 2008 22:03:00
Répondre     Citer    
Re: utilisation de 'trap'
Envoyé par: Fanch

Bon alors j'ai repris ton script :

#!/usr/bin/env bash

# Script pour un chronomètre
# affiche le temps écouler depuis le lancement du script
#
sortie() {
    tput sgr0
    clear
    exit 0
}

trap 'sortie' 2

HD=$(date +%s)
## Cette partie est peut-être retors, mais je ne m'imagine pas convertir des secondes en sexagésimal
SC=$(date +%S)  #   #   #   # afiche les secondes en cours
tpfx=60 #   #   #   #   # 60
let csc=$tpfx-$SC   #   #   # calcul les secondes en cours jusqu'à 60 secondes

while : ; do
clear
HC=$(date +%s)
let chronoH=($HC-$HD)/3600 # affiche des heures
let chronoM=($HC-$HD)/60   # affiche des minutes
SC2=$(date +%S --date +"$csc"seconds)   # affiche les secondes en cours avec un décalage de sdoif secondes
echo -n -e '\E[1;37;46m'"$chronoH $chronoM $SC2 "
sleep 1 #.5 on peut régler le rafraîchissement
tput sgr0 # restauration des paramètres d'affichage par défaut
done

Et quand je run :
$ ./plouf.sh

ça m'affiche le chrono ; un coup de ctrl+c et je reviens aussi sec dans la console normale.

------- <br />
La meilleure façon de prédire le futur, c'est de l'inventer ~ Alan Kay

Poste le Thursday 21 February 2008 10:24:24
Répondre     Citer    
Re: utilisation de 'trap'
Envoyé par: |/|BaH

Et tu ne te fais pas non plus déloggué par exit? (cf. [lea-linux.org])

De mon côté, je l'ai essayé sur une autre distro basée sur Debian Etch, puis sur un autre ordi avec la même Debian Etch que sur mon poste principal, et...
j'ai le même comportement de m:censored:

J'veux pas aller sur fedora:,(

Poste le Thursday 21 February 2008 15:27:48
Répondre     Citer    
Re: utilisation de 'trap'
Envoyé par: Fanch

t'auras le même comportement partout (moi je suis sous Gentoo) ; ça dépend pas de la distro.

le exit met fin au shell qui l'appelle ; c'est à dire ici le script (mais pas le shell depuis lequel j'appelle le script).
Après ça dépend comment t'appelles le script (t'en fais bien un exécutable puis tu l'appelles comme un binaire ? )



------- <br />
La meilleure façon de prédire le futur, c'est de l'inventer ~ Alan Kay

Poste le Thursday 21 February 2008 16:52:54
Répondre     Citer    
Re: utilisation de 'trap'
Envoyé par: |/|BaH

J'irai pas sur fedora !!!:-))

Tout ça pour ça!
Y a rien de pire pour l'ego que de buter sur des trucs aussi basiques.

Mais j'avais compris que lancer un script par :
. ~/rep/script
~/rep/./script, ou
cd ~/rep; ./script
était équivalent, et qu'il n'était pas nécessaire de taper 'sh' avant, ni de créer un lien dans un répertoire d'éxécutables (cf. [cern91.tuxfamily.org]).

Voici un sujet résolu


Je te remercie sincèrement de ton opiniâtreté.

Poste le Thursday 21 February 2008 18:22:09
Répondre     Citer    
Re: utilisation de 'trap'
Envoyé par: Fanch

juste un truc :
- avoir le script dans un répertoire du PATH
- appeler /chemin/absolu/script.sh
- appeler ../chemin/relatif/script.sh
- appeler cd chemin ; ./script.sh
lorsque le script est exécutable (on a fait chmod +x script) et que la première ligne est "#!/usr/bin/env bash", c'est bonnet blanc et blanc bonnet.

en revanche l'appel ". script" est fondamentalement différent : "." c'est un raccourci pour "source" ; par exemple :
". script.sh" et "source script.sh".

si ton script contient juste les trois lignes :
#!/usr/bin/env bash
export TOTO="toto"
echo $TOTO

alors :
$ ./script.sh
toto
$ echo $TOTO

$ source script.sh
toto
$ echo $TOTO
toto



... et ça c'est pas rien ;-) (et zou, echo fedora 2>&1 >/dev/null .... troll inside yawning smiley) )



------- <br />
La meilleure façon de prédire le futur, c'est de l'inventer ~ Alan Kay

Poste le Tuesday 26 February 2008 22:15:28
Répondre     Citer    
Re: utilisation de 'trap'
Envoyé par: |/|BaH

C'est beaucoup de finesse, voire de "ténuité". J'avoue avoir du mal à saisir la différence.
J'observe effectivement des différences de comportement des scripts selon le mode de lancement, mais ça rentre pas dans cette bille de bois dur qui me sert de tête...
J'ai cherché, suite à tes commentaires, des explications, mais nib. Hormis le lien précédemment cité. Je n'ai peut-être pas su trouver les mots pour charmer Google...

Poste le Wednesday 27 February 2008 13:06:59
Répondre     Citer    
Re: utilisation de 'trap'
Envoyé par: oudoubah

source (ou . ) correspond à "inclure" dans ton shell courant le contenu du fichier, un peu comme un "include" dans d'autres langages.
Si tu affectes des variables, ou si tu effectues des commandes, elles seront faites dans ton shell courant.
Comme règle, on pourrait dire qu'on ne fait un source d'un fichier que si il définit des variables ou des fonctions. Au final, il ne doit rien exécuter.

Lorsque tu lances un script, alors il y a un nouveau shell qui est créé, et tout se fait dans ce sous-shell. Rien de ce qui est fait dans ce sous-shell n'affecte le shell parent (fonctions, variables, commande exit).

Tu as lu les docs. Tu es devenu un informaticien. Que tu le veuilles
ou non. Lire la doc, c'est le Premier et Unique Commandement de
l'informaticien.
-+- TP in: Guide du Linuxien pervers - "L'évangile selon St Thomas"

Poste le Wednesday 27 February 2008 17:10:23
Répondre     Citer    
Re: utilisation de 'trap'
Envoyé par: Sve@r

Citation
|/|BaH
C'est beaucoup de finesse, voire de "ténuité".
J'avoue avoir du mal à saisir la différence.
J'observe effectivement des différences de
comportement des scripts selon le mode de
lancement, mais ça rentre pas dans cette bille de
bois dur qui me sert de tête...
J'ai cherché, suite à tes commentaires, des
explications, mais nib. Hormis le lien
précédemment cité. Je n'ai peut-être pas su
trouver les mots pour charmer Google...

Il faut bien comprendre que dans Unix, dès que tu demandes une exécution de code (ls, date, grep, script.sh) ton shell lance un sous-shell.
- Le shell dans lequel tu travailles se met en mode "attente"
- Le sous-shell a la charge d'exécuter le "ls", le "date", le "grep" ou le "script.sh"
Dès qu'il a fini, il disparait et le shell qui était en attente (le tien) reprend la main

Tout ça c'est transparent mais ce mécanisme permet de
- lancer une exécution en arrière plan (avec "&" en fin de ligne) => ton shell n'attend plus la fin de l'autre
- lier les différents codes via des pipes => ls |more => chaque commande est exécutée dans un shell bien distinct et le premier reverse sa sortie dans le second
Problèmatique => toute la mémoire allouée pour le code, le script, disparait lorsque le script se termine et ton shell courant ne récupère rien. Mais est-ce vraiment un problème ???

En revanche, demander un ". script" ou "source script" demande au shell courant de ne pas dédier le script à un autre => toutes les variables restent au niveau de ton shell

Démo => tu crées un script "toto.sh" qui contient le code suivant
#!/bin/sh
a="Salut"
echo $a

Puis tu lances "./toto.sh" et ensuite tu tapes "echo $a" => tu n'auras rien
Ensuite tu lances "source ./toto.sh" et ensuite tu tapes "echo $a" => tu obtiendras "salut"

L'homme qui murmurait à l'oreille des pingouins
[fr.lang.free.fr]

Poste le Thursday 20 March 2008 13:02:43
Répondre     Citer    
Re: utilisation de 'trap'
Envoyé par: |/|BaH

J'ai dû lire trop vite un article, et ne retenir que GNU/Linux n'était pas sensible aux extensions de fichier (contrairement à tu sais qui...).

Donc je nomme les scripts, dont le résultat ne doit pas interagir avec le shell courant, 'fichier_z.sh'. Sinon, je peux les nommer ainsi que je le désire, même fichier_y.sh. Sachant que, pour que le résultat soit encore utilisable par le shell courant, ou pour "inclure son contenu" dans un script, je dois mettre un point et un espace devant.


L'écorce se fend, et l'on voit apparaître la pointe d'un bourgeon.
Serait-ce le printemps...même pour les billes de bois?

Poste le Friday 21 March 2008 02:15:12
Répondre     Citer    
Re: utilisation de 'trap'

Bonjour tous,

L'indicateur de temps écoulé, pour lequel j'ai débuter ce sujet, fonctione très bien et quitte très bien.

Je relève cependant ce sujet concernant l'utilisation de trap, car je m'interroge (ainsi que google) sur la possibilité de "trapper" d'autres combinaisons de touche que Ctrl-C.

Je me suis attelé à la rédaction d'un script pour lire de l'audio dans une console virtuelle :
Je m'afiche les morceaux contenus dans un certain répertoire . J'utilise aplay, et je peux l'interrompre avec un Ctrl-C (normal !), puis je reviens au choix d'un morceaux.

A ce moment là, je voudrais, si je décide de quitter l'éxécution du script qu'un fichier temporaire soit purgé.

Le problème c'est que pour ce faire, je ne peux pas utiliser trap avec Ctrl-C qui m'est nécessaire pour interrompre la lecture...

Est-ce clair ?

Bon, je vous met le code en question :
clear 

echo -e " $(basename $RepMusq) :\\n ############"

for i in $(ls $RepMusq/*raw); do 
wc -c $i |\
 awk '{ mn=$1/48000/4/60; sc=$1/48000%60; printf substr($2,25) " -:- %1.0f", mn; printf ",%02.0f mn", sc }' |\
 awk 'BEGIN { FS=".raw"} {print $1 $2 }' >> $RepMusq/$(date +%Y%m%d).files
done

pr -W $(tput cols) --columns=3 -n -T $RepMusq/$(date +%Y%m%d).files

tput sc

PLAY(){
stop() {
> $RepMusq/$(date +%Y%m%d).files
echo " fin du programme"
exit 0
}
trap 'stop' # ? # Je l'ai mis là car c'est à ce moment là que j'en ai besoin

echo " Saisis le numéro d'un morceau à jouer..."
read play
aplay -D hw:0 -f S16_LE -r 48000 -c2 -t raw $RepMusq/$(sed -n "$play"p $RepMusq/$(date +%Y%m%d.files) | cut -d" " -f 1).raw
tput -S <<!
cuu1
rc
cuu1
cvvis
sgr0
ed
!
}
while : ; do
PLAY
done

echo "le programme a quitté"

Je pourrais passer par un
read bla
case $bla in
[Qq]*)> $RepMusq/$(date +%Y%m%d).files
exit 0
;;
[1-9]*) PLAY
;;
esac
mais bon, si trap peut "trapper" d'autres combinaisons de touches que Ctrl-C, ce ne serait pas plus mal...

Je vous remercie de votre attention, et de vos commentaires...

Poste le Wednesday 28 May 2008 16:31:54
Répondre     Citer    
Re: utilisation de 'trap'

trap n'attrape pas des combinaisons de touches, mais des signaux.

Les tty (par exemple, l'entrée du shell dans un terminal) sont des choses compliquées dans le noyau (comprendre le contexte historique des Teletypes, relire le Unix hater handbook pour une critique, et se plonger dans un bon bouquin comme Advanced Unix Programming pour les détails sur les ttys). Ils peuvent être configurés (et le sont généralement) pour que Ctrl-C envoie un signal SIGINT au processus (plus exactement, à un groupe de processus ou une session, j'ai oublié les détails). La configuration d'un tty se fait par la commande stty (qui fait des appels systèmes compliqués).

Un shell script ne reçoit pas des combinaisons de touches, mais des signaux!

A priori, évites de toucher à la configuration du tty courant (en lançant stty) car elle demeure assez permanente...

----

Basile STARYNKEVITCH

Membre de l'APRIL « promouvoir et défendre le logiciel libre » - adhérez vous aussi à l'APRIL!

Projet logiciel libre: RefPerSys

Poste le Wednesday 28 May 2008 16:57:26
Répondre     Citer    
Re: utilisation de 'trap'
Envoyé par: faqerh

qd une commande lit a partir du terminal, tu peux faire un C-d
le terminal envoie alors un EOF a la commande.

sinon tu peux trapper plus d'un signal la fois man bash
pour le signal envoyer qd un script se termine normalement
INT KILL HUP sont les autres signaux plus lassiques

Poste le Saturday 31 May 2008 12:00:14
Répondre     Citer    
Re: utilisation de 'trap'

:-cb
@#%! :-F trap
vous voyez ce que je veux dire...^^
Citation
trap
Argh... même pas mal!!!
Il se moque de moi.


Citation
Basile STARYNKEVITCH
trap n'attrape pas des combinaisons de touches, mais des signaux.
...signaux qui sont envoyés, au processus à l'avant-plan, par des combinaisons de touches.
Ce n'est pas anodin, merci Basile.


Finalement, je ne veux plus quitter le script. "L'excellente" idée, que j'ai eue, en rédigeant mon post, d'utiliser 'case...in...esac', m'offre davantage de possibilités : [Q]uitter, [E]nregistrer, ouvrir une interface simple pour terminal virtuel (à faire, ou à trouver : je n'ai pas encore cherché) qui permette d'utiliser les caractéristiques principales de 'sox'...

Mais quand même, est-ce que quelqu'un disposerait d'un "tableau de concordance" entre 'trap -l' et 'stty -a', parce que, si dans le second j'ai un "eof = ^D", dans le premier je ne vois pas de "SIGEOF"...

Ah! j'ai googlé, pendant deux jours. Là, j'ai les yeux qui fondent. J'vais p'têt essayer " "trap -l" & acccordeon & "stty -a" ", p'têt que ça marchera mieux...^^


avec mes remerciements renouvelés

Poste le Saturday 31 May 2008 17:50:47
Répondre     Citer    

Veuillez vous authentifier auparavant pour commenter.

 

Ce forum !
utilisation de 'trap'
Pour poser vos questions sur les scripts shell, le Perl, le C, etc... Attention : nous ne sommes pas des spécialistes du dev, ce forum est juste pour de petites aides ponctuelles concernant le développement et les outils de développement.

Sauf mention contraire, les documentations publiées sont sous licence Creative-Commons