IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Fonctions en parallèle dans un seul script


Sujet :

Shell et commandes GNU

  1. #1
    Invité
    Invité(e)
    Par défaut Fonctions en parallèle dans un seul script
    Bonjour,

    Je m'amuse à essayer de faire un petit jeu en shell et je bloque sur un truc.
    J'ai une fonction d'affichage qui boucle et que je lance en tâche de fond. Mais comme je la lance en tâche de fond elle ne récupère plus la nouvelle valeur des variables ...

    Une idée pour résoudre ce problème?

    Ci-dessous un exemple très simplifié de ce que j'essaie de faire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    item=0
     
    affichage () {
    temps=0
    while [ $item -eq 0 ]
    do
    clear
    echo "temps : $ temps"
    sleep 1
    temps=$((temps+1))
    done
    }
     
    affichage &
    item=1
    Item ne vaut jamais 1 dans affichage

    Cela pourrait être résolu en passant par des fichiers mais j'aimerais avoir quelques chose de plus optimisé.
    Je me demande si c'est vraiment possible ...

    Merci d'avance

  2. #2
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 287
    Par défaut
    Bonjour

    Il me semble que tu es mûr pour t'intéresser aux tubes nommés (named pipes).
    Cest comme command1 | command2 sauf que ce n'est pas forcément en même temps. Cela permet la discussion entre processus.

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    mkfifo montube
    echo "youpi!" >montube &
    sleep 2
    cat montube
    echo tralala >montube &
    echo tsointsoin >montube &
    sleep 1
    cat montube
    rm -f montube

  3. #3
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 642
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 642
    Par défaut
    Bonjour,

    je ne fais rien afficher par une tâche qui s'exécute en arrière plan, car je ne peux pas toujours savoir ce qui sera alors affiché à l'écran, et qui pourrait, à ce moment, être recouvert.

    dans ta situation, je ferais le test sur $item à l'extérieur de la fonction, pour, si la condition est remplie, exécuter ponctuellement la fonction, sinon pour tuer la fonction.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  4. #4
    Invité
    Invité(e)
    Par défaut
    @flodelarab:
    Cela me semble une bonne idée. Le tube créé sur le disque semble toujours être vide quand on fait un ls. C'est juste un pointeur vers un emplacement mémoire (comme le p semble l'indiquer) ?

    Vu que c'est un fifo (first in first out) je devrais pouvoir y stocker plusieurs lignes et les lire après comme tu as mis dans ton exemple. Mais j'ai l'impression qu'on est obligé de tout lire d'un coup car le read n'a pas l'air de marcher. C'est bien ça?

    @N_BaH: c'est exact mais infaisable dans ce que j'essaye de faire.

  5. #5
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 342
    Par défaut
    Bonjour,

    En fait, oui et non pour le read, c'est le echo du read qui ne fonctionne pas sur un pipe.
    il faut donc faire un echo pour écrire dans le pipe et tu peux faire un read pour lire dedans.

    Voici un lien avec un exemple:http://www.developpez.net/forums/d13...s/#post7296508

  6. #6
    Invité
    Invité(e)
    Par défaut
    Ok, je comprend tout à fait l'exemple.
    Je testerais ça demain pour voir si j'arrive à faire ce que je veux.

    Merci en tout cas.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Finalement ça ne marche pas trop comme je veux.
    Le tube nommé ne contient plus rien une fois qu'on l'a lu et la lecture se met alors en pause ...

    J'essaie de faire un petit jeu du serpent en shell (c'est un défi que je me suis lancé )
    Pour le moment je suis donc obligé de passer par un fichier physique ...
    Voici le code actuel (ça déplace juste le X à l'écran). Si vous avez des idées d'amélioration pour ce qui a déjà été fait, je suis preneur.

    Fichier jeu3.sh (obligé de faire un "read -n3" pour les flèches du clavier)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #!/bin/bash
     
    touche=""
    continuer=true
    echo "bas" > jeu3_tmp
     
    ./jeu3_affichage.sh $$ &
    while [ $continuer == true ]
    do
    	case "$touche" in
    	$'\x1b[A') echo "haut" > jeu3_tmp;;
    	$'\x1b[B') echo "bas" > jeu3_tmp;;
    	$'\x1b[C') echo "droite" > jeu3_tmp;;
    	$'\x1b[D') echo "gauche" > jeu3_tmp;;
    	q|Q) continuer=false;;
    	esac
     
    	read -s -n3 touche;
    done
    Fichier jeu3_affichage.sh
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    #!/bin/bash
     
    main_sh=$1
    debut=$(date "+%s")
    #         0123456789012345678901234567890123456789012345678901234567890
     ligne_0='#############################################################'
     ligne_X='#                                                           #'
    ligne_10='#############################################################'
     
    item=0
    item_x=5
    item_y=3
    end=false
     
    x=30
    y=5
    direction="droite"
     
    recuperation_variable () {
    	read direction
    }
     
    ligne () {
    	ligne_tmp="#"
     
    	for ((i=1; i<60; i++))
    	do
    		if [ $1 -eq $y ] && [ $i -eq $x ]
    		then
    			ligne_tmp+="X"
    		elif [ $1 -eq $item_y ] && [ $i -eq $item_x ]
    		then
    			ligne_tmp+="o"
    		else
    			ligne_tmp+=" "
    		fi
    	done
    	ligne_tmp+="#"
    	echo "$ligne_tmp"
    }
     
    affiche () {
    	ligne_1=`ligne 1`
    	ligne_2=`ligne 2`
    	ligne_3=`ligne 3`
    	ligne_4=`ligne 4`
    	ligne_5=`ligne 5`
    	ligne_6=`ligne 6`
    	ligne_7=`ligne 7`
    	ligne_8=`ligne 8`
    	ligne_9=`ligne 9`
     
    	if [ $x -lt 1 ] || [ $x -gt 59 ] || [ $y -lt 1 ] || [ $y -gt 9 ]
    	then
    		end=true
    	else
    		clear
    		echo -e "Entrer q pour quitter\n$ligne_0\n$ligne_1\n$ligne_2\n$ligne_3\n$ligne_4\n$ligne_5\n$ligne_6\n$ligne_7\n$ligne_8\n$ligne_9\n$ligne_10"
    		sleep 0.5
    	fi
    }
     
    kill -0 $main_sh 2>/dev/null
    while [ $? -eq 0 -a $end == false ]
    do
    	affiche
     
    	recuperation_variable < jeu3_tmp
    	case "$direction" in
    	"gauche") x=$((x-1));;
    	"droite") x=$((x+1));;
    	"haut") y=$((y-1));;
    	"bas") y=$((y+1));;
    	esac
     
    	kill -0 $main_sh 2>/dev/null
    done
     
    if [ $end == true ]
    then
    	temps=$(($(date "+%s")-$debut))
    	echo "You survived $temps seconds."
    	echo "You found $item item."
    	kill -9 $main_sh 2>/dev/null
    fi

  8. #8
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 642
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 642
    Par défaut
    Code jeu3 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #!/bin/bash
     
    tmp=jeu3_tmp
    declare -i continuer=1
    mkfifo $tmp
    ./jeu3_affichage $$ $tmp &
    affichage=$!
     
    echo $'^[[B' > $tmp &
    while ((continuer)) 
    do
       read -s -n3 touche;
       [[ $touche = [qQ] ]] && continuer=0
       echo "$touche" > $tmp &
    done
    { kill $affichage; rm $tmp;} 2>/dev/null
    exit
    Code jeu3_affichage : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    tmp=$2
    #...
       read direction < $tmp
       test -n "$direction" && directionBKP="$direction"
       case ${direction:-$directionBKP} in
          $'^[[D') x=$((x-1));;
          $'^[[C') x=$((x+1));;
          $'^[[A') y=$((y-1));;
          $'^[[B') y=$((y+1));;
       esac
    il faut encore appuyer sur «Entrée» après «qQ», car ce n'est qu'un caractère et non trois comme les touches de direction
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  9. #9
    Invité
    Invité(e)
    Par défaut
    C'est vrai que le q pour quitter n'est pas terrible vu que ça ne fait pas 3 caractères ...

    Ca ne peut lire le tube nommé que s'il y a quelque chose dedans (ou alors le fonctionnement dans le script est différent de celui dans le terminal) ... Et à chaque fois ça supprime une ligne ...

    J'ai mis ta partie du jeu3_affichage dans la boucle while mais l'affichage ne change pas. J'ai du faire une erreur.
    En tout cas je vais regarder un peu plus ton code car il y a des syntaxes que je ne connais pas

    Dans ma version avec le fichier physique ça prend toujours la dernière direction indiquée. Ce qui permet de faire bouger le X à l'écran toute les demi-secondes sans attendre qu'on appuie sur une des flèches.

    [Edit] Quand à la syntaxe de ton code, ai-je juste?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
       [[ $touche = [qQ] ]] && continuer=0
       echo "$touche" > $tmp &
     
    =
     
    if [ $touche = q ] || [ $touche = Q ]
    then 
    continuer=0
    fi
    echo "$touche" > $tmp &
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
       test -n "$direction" && directionBKP="$direction"
       case ${direction:-$directionBKP} in
    ...
     
    =
     
    if [ "$direction" != "" ]
    then
    directionBKP="$direction"
    case $direction in
    ...
    else
    case $directionBKP in
    ...
    fi
    Dernière modification par Invité ; 12/07/2013 à 12h02.

  10. #10
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 642
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 642
    Par défaut
    Quandt à la syntaxe de ton code, ai-je juste?
    oui, c'est bien ça.

    Ca ne peut lire le tube nommé que s'il y a quelque chose dedans (ou alors le fonctionnement dans le script est différent de celui dans le terminal) ...
    oops, j'ai oublié de mettre le timeout :
    Code jeu3_affichage : Sélectionner tout - Visualiser dans une fenêtre à part
    read -t 0.5 direction
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  11. #11
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 287
    Par défaut
    La solution est ailleurs. Voici ce que je propose. Utilisons tmpfs. C'est un système de fichier qui utilise la ram. Si tu veux créer et monter un dossier tmpfs, voici un bon lien à lire.
    Personnellement, quand je tape mount, il m'indique que j'ai déjà un dossier monté en tmpfs. C'est /dev/shm. Je vais donc utiliser ce dossier. Fabrique arene.txt (ton decor) et teste ce code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #!/bin/bash
     
    ecran="/dev/shm/ecran.txt"
    coord_x=10
    coord_y=2
     
    placer_tete()
    {
        sed -i $2's/./X/'$1 $ecran
    }
     
    effacer_tete()
    {
        sed -i 's/X/O/' $ecran
    }
     
    afficher()
    {
        clear
        echo "Tour $i"
        cat $ecran
    }
     
    cat arene.txt >$ecran
    afficher
    sleep 2
     
    for i in $( seq 10 )
    do
        effacer_tete $coord_x $coord_y
        coord_y=$((coord_y+1))
        placer_tete $coord_x $coord_y
        afficher
        sleep 1
     
    done
    J'obtiens cela à la fin:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    Tour 10
    ------------------(MON_ARENE)---------------------
    |                                                |
    |        O                                       |
    |        O                                       |
    |        O                                       |
    |        O                                       |
    |        O                                       |
    |        O                                       |
    |        O                                       |
    |        O                                       |
    |        O                                       |
    |        X                                       |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    |                                                |
    --------------------------------------------------
    Et je n'ai pas utilisé le disque dur !

  12. #12
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 642
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 642
    Par défaut
    Citation Envoyé par Flodelarab
    La solution est ailleurs
    seule LA vérité est ailleurs
    un problème peut avoir plusieurs solutions (plus ou moins bonnes).


    for i in $( seq 10 )...
    ou
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    for ((i=1;i<=10;i++))
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  13. #13
    Invité
    Invité(e)
    Par défaut
    J'ai bien les ovni ^_^

    @N_BaH: oups, j'aurais dû me relire. J'ai toujours du mal avec le "quant à"
    L'option -t me pose problème lorsque ce n'est pas un entier. Il faut peut être une version récente de bash? J'en ai une vieille...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bash: read: 0.5 : spécification de délai d'expiration non valable
    @Flodelarab: c'est bon à savoir. En tout cas ça fonctionne bien sur ma machine virtuelle
    Par contre je comptais utiliser des tableaux pour faire disparaître la queue du serpent au fur et à mesure.

    Il faudra que je teste ça sur cygwin (et aussi que j'y installe clear)

    ps: j'ai bien fait de faire un poste pour ce problème. J'apprends plein de choses

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. ode45 résolue dans un seul script
    Par barns_89 dans le forum MATLAB
    Réponses: 3
    Dernier message: 02/12/2013, 17h28
  2. nom de colonne en fonction du resultat(dans une seule requete)
    Par chezdevelopping dans le forum Requêtes
    Réponses: 7
    Dernier message: 14/06/2011, 12h30
  3. Réponses: 6
    Dernier message: 09/06/2009, 10h09
  4. Réponses: 1
    Dernier message: 17/12/2008, 08h39
  5. [HTML] feuilles dans un seul script
    Par fourgeaud dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 18/11/2005, 23h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo