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

Réseau Discussion :

SSH "return" dans des fonctions


Sujet :

Réseau

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 39
    Points : 29
    Points
    29
    Par défaut SSH "return" dans des fonctions
    Bonjour,

    J'ai un probleme avec la commande return.

    J'ai une fonction fonction_1 qui est appele dans le main. Dans cette fonction, il y a a plusieurs endroit des return (si j'ai une erreur, je desire sortir de la fonction fonction_1 sans l'executer jusqu'au bout).

    J'aimerais maintenant deplacer certains traitements de la fonction_1 dans une nouvelle fonction, fonction_2, qui sera appelee dans fonction_1.

    Ma question est la suivante : si je fait un return dans la fonction_2, est ce que je quitterais aussi la fonction_1 (comportement souhaite). Si non, comment puis je faire ? (exit quitte tout le shell).

    Merci d'avance

    Geoffrey

  2. #2
    Membre éprouvé
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Points : 977
    Points
    977
    Par défaut
    Salut,

    a priori, si tu fait un return dans fcnt_2, tu reviens dans fcnt_1 (et pas dans main)

    tu peux decider de coder une valeur de retour pour fcnt_2 (genre return 1 si erreur, 0 sinon), et tester la valeur de retour dans fcnt_1:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int ret = fcnt_2(......);
    if (ret==1){
         return(ta_valeur_de_retour_de_fcnt_1); /*et la tu reviens dans main*/
    else{
    /*fcnt_2 s est bien passee*/
    .....
    et tu testes a chaque appel de fcnt_2

    il y a peut etre plus simple, mais au moins, comme ca, tu controles de maniere plus efficace ta fonction fcnt_2.

    voila!

    ++
    Pouic

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 39
    Points : 29
    Points
    29
    Par défaut
    Cette solution ne m'arrange pas trop, je pensais pouvoir gagner un peu de place. Mon code se presente sous cette forme

    ce a quoi j'aimerais arriver :
    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
     
    fonction_1()
    {
      cmd="commande shell a"
      fonction_2
     
      cmd="commande shell b"
      fonction_2
     
      cmd="commande shell c"
      fonction_2
     
       ...
    }
     
    fonction_2()
    {
      if ! $cmd; then
        echo "$cmd a echoue."
        # --> c'est la que j'aimerais mettre un "return" pour sortir de la fonction_1 ...
      fi
    }
     
    #main
     
    fonction_1
     
    ...
     
    #end main
    ce que j'ai actuellement :
    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
     
    fonction_1()
    {
      cmd="commande shell a"
      if ! $cmd; then
        echo "$cmd a echoue."
        return
      fi
     
      cmd="commande shell b"
      if ! $cmd; then
        echo "$cmd a echoue."
        return
      fi
     
      cmd="commande shell c"
      if ! $cmd; then
        echo "$cmd a echoue."
        return
      fi
     
       ...
    }
     
    #main
     
    fonction_1
     
    ...
     
    #end main

  4. #4
    Membre averti

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 289
    Points : 342
    Points
    342
    Par défaut
    Tu peux utiliser les opérateurs && et || pour chaîner des opérations:commande1 est exécutée, et si son résultat est zéro, commande2 est exécutée, sinon commande2 ne l'est pas.l'inverse: si commande1 renvoie zéro, commande2 n'set pas exécutée.

    Et aussi la variable $?, qui contient le code de retour de la dernière commande executée.

    Donc un truc du genre
    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
    #! /bin/sh
    fonction2()
    {
            $1 || {
                    RET=$?
                    echo "$1 a echoué"
                    return $RET
            }
    }
     
    fonction1()
    {
            fonction2 'echo succes' || return $?
     
            fonction2 'echoz "echec"' || return $?
     
            fonction2 'echo disparu' || return $?
    }
     
    # un "main" réduit à sa plus simple expression:
    fonction1
    me donne le résultat suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ . ./essai.sh 
    succes
    bash: echoz: command not found
    echoz "echec" a echoué
    et le code de retour est bien 127, qui est le code d'erreur d'une fonction non trouvée... (ok, mon exemple est un peu bancal)

    Si le code de retour de ta fonction1 ne dépend pas du code de retour de la commande qui a échoué, tu peux faire plus simple:
    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
    #! /bin/sh
    fonction2()
    {
            $1 || {
                    echo "$1 a echoué"
                    return -1
            }
    }
     
    fonction1()
    {
            fonction2 'echo succes' || return 1
     
            fonction2 'echoz "echec"' || return 1
     
            fonction2 'echo "disparu"' || return 1
    }
     
    # un "main" réduit à sa plus simple expression:
    fonction1
    Ou encore, si les commandes n'ont pas une syntaxe trop compliquée (i.e. pas trop de caractères ' " ou \, et pas trop longues) :
    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
    #! /bin/sh
     
    fonction1()
    {
            for cmd in 'echo succes' \
                       'echoz "echec"' \
                       'echo "disparu"'
            do
                    $cmd || {
                            echo "$cmd a echoué"
                            return 1
                    }
            done
    }
     
    # un "main" réduit à sa plus simple expression:
    fonction1
    On pourrait aussi conserver les commandes dans un tableau, puis passer ledit tableau à fonction1... Bref, tu as plein de solutions, suivant ton problème exact: quelle est la valeur de ton code de retour ? quelles sont ces commandes ? sont-elles connues à l'avance, simples ?

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 39
    Points : 29
    Points
    29
    Par défaut
    Les commandes testees sont generalement assez complexes, avec des ',",/,...

    Ce sont principalement des commandes liees aux bases de donnees (Informix, PGS, MySQL, Sybase ASA, ...) : demarrage de base, creation de base, creation d'user, ...

    J'ai pour chaque base deux fonctions principales : prepareNOMDELABASE et cleanNOMDELABASE

    Autre point, le code retour n'est pas tres important, je cherche seulement a savoir si $? est egal 0 ou pas (OK ou pas OK).

    Un exemple : prepareSybaseASA()
    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
     
    prepareSybaseASA()
    {
      begin_test "QA40ODI$dbcode" "Prepare Sybase ASA $dbcode database"
     
      # 1. we get Sybase ASA version
      if ! getSybaseASAVersion; then
        end_test "NO" "Getting the MySQL version failed."
        odi_todo=0
        return
      else
        dboption="-dv $dbversion"
      fi
     
      # 2. we check id Sybase database entity already exist
      if [ -e ${dbname}.db ]; then 
        # if yes, we erase it
        dberase -y -q ${dbname}.db >/dev/null 2>&1
      fi
     
      # 3. we create a new Sybase database entity
      cmd="dbinit -c -b $dbname"
      if ! eval $cmd >/dev/null 2>&1; then
        end_test "NO" "$cmd failed."
        odi_todo=0
        return
      fi
     
      # we wait for the dbinit process to end
      sleep 10
     
      # 4. we run the database server as a daemon
      if ! checkSybaseASAIsRunning ; then
        cmd="dbspawn dbeng${dbversion} $dbname"
        if ! eval $cmd >/dev/null 2>&1; then
          end_test "NO" "$cmd failed."
          odi_todo=0
          return
        fi
      fi
     
      # 5. we declare a database user dedicated to odi test
      cmd="dbisqlc -c \"uid=DBA;pwd=SQL\" grant connect to $logname identified by $logpasswd"
      if ! eval $cmd >/dev/null 2>&1; then
        end_test "NO" "$cmd failed."
        odi_todo=0
        return
      fi
      cmd="dbisqlc -c \"uid=DBA;pwd=SQL\" grant resource to $logname"
      if ! eval $cmd >/dev/null 2>&1; then
        end_test "NO" "$cmd failed."
        odi_todo=0
        return
      fi
     
      # 6. we need to change some database options in order to make the test working
      cmd="dbisqlc -c \"uid=DBA;pwd=SQL\" set existing option ${logname}.MAX_CURSOR_COUNT = 0"
      if ! eval $cmd >/dev/null 2>&1; then
        end_test "NO" "$cmd failed."
        odi_todo=0
        return
      fi
      cmd="dbisqlc -c \"uid=DBA;pwd=SQL\" set existing option ${logname}.MAX_STATEMENT_COUNT = 0"
      if ! eval $cmd >/dev/null 2>&1; then
        end_test "NO" "$cmd failed."
        odi_todo=0
        return
      else
        end_test "OK" ""
      fi
    Sinon j'avais oublie les operateurs && et || et je crois que c'est effectivement la piste a suivre.

    Ca pourrait faire quelque chose du genre :

    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
     
    #! /bin/sh
    fonction_1()
    {
      cmd="ma_commande"
      fonction_2 || return
    }
     
    fonction_2()
    {
      if ! eval $cmd >/dev/null 2>&1; then
        res=$?
        end_test "NO" "$cmd failed."
        odi_todo=0
        return  $res
      else
        return 0
      fi
    }
     
    #main
    fonction_1
    Est ce que c'est correct ??

    Ou est ce que ma fonction_2 pourrait se resumer a :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    fonction_2()
    {
      if ! eval $cmd >/dev/null 2>&1; then
        end_test "NO" "$cmd failed."
        odi_todo=0
        return 666
      fi
    }

  6. #6
    Membre averti

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 289
    Points : 342
    Points
    342
    Par défaut
    Ta dernirèe solution sera la plus efficace, vu que tu te fiches du code de retour... Tu pourrais remplacer le 'if ! eval ....' par un || bien placé, mais je ne sais pas si point de vue maintenance/relecture ça serait mieux.

    Au passage, tu es sûr devouloir rediriger toutes les sorties standard et d'erreur vers /dev/null ?

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 39
    Points : 29
    Points
    29
    Par défaut
    J'ai pas encore teste (manque de temps...) mais je vais essayer la deuxieme soluce, merci pour l'info des || et &&

    Pour la lisibilite du code, mieux vaut que je laisse le if ! eval (parce que la j'ai pas d'autre ID et que la fonction est deja assez light )

    Et pour la redirection des commandes dans /dev/null, c'est une obligation pour moi, car les shell que je developpe (qui font partie de jeux de tests pour l'application que ma boite developpe), sont appele par une commande developpee en interne qui est tres restrictive au niveau syntaxique (et qui attend des mots clefs genre OK, NO, PASSED ou encore WARNING suivi d'une description et precede d'un code donc la sortie standard ou l'erreur ne nous interesse pas specialement).

    Par contre cela pose de temps en temps un probleme : la commande echoue mais $? est egal a 0... Mais c'est tres rare !

    EDIT : j'ai enfin put modifier le code de projet et ca tourne nickel, merci

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

Discussions similaires

  1. Complexité dans des fonctions imbriquées
    Par gmatu dans le forum Algorithmes et structures de données
    Réponses: 9
    Dernier message: 26/08/2011, 19h26
  2. Création d'objet dans des fonctions
    Par fafabzh6 dans le forum R
    Réponses: 5
    Dernier message: 22/07/2008, 15h30
  3. [MySQL] [MySQLi] Désagrément lié à son utilisation dans des fonctions
    Par getdown dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 04/01/2008, 23h47

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