Forum Programmation.autre [RÉSOLU] Bash utiliser variable dans une commande du style result=$(commande | grep $variable)

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
3
25
mai
2017

J'ai du mal a formuler cette question à Google alors je vous la formule a vous :P

Le problème vient de la variable $mountPoint, en effet lorsque je place directement la valeur au lieu de la variable, cela fonctionne.
Donc la question : comment suis-je censé spécifier la variable pour l'incorporer dans ce genre de commande

result=$(mount | grep "$mountPoint" | wc -l)

exemple

FONCTIONNE

#!/bin/bash

result=$(mount | grep "/media/monPath" | wc -l)
if [ ${result} = "1" ];then
        echo "montage effectif"
else
        echo "mont```age not work"
fi

NE FONCTIONNE PAS

#!/bin/bash

mountPoint="/media/monPath"
result=$(mount | grep "$mountPoint" | wc -l)
if [ ${result} = "1" ];then
        echo "montage effectif"
else
        echo "montage not work"
fi

NE FONCTIONNE PAS

#!/bin/bash

mountPoint="/media/monPath"
result=$(mount | grep "${mountPoint}" | wc -l)
if [ ${result} = "1" ];then
        echo "montage effectif"
else
        echo "montage not work"
fi

résolu : merci à vous tous pour vos solutions et commentaires fort intéressant !
Solution dans les commentaires : https://linuxfr.org/forums/programmationautre/posts/bash-utiliser-variable-dans-une-commande-du-style-result-commande-grep-variable#comment-1702904

Voici le script final en suivant vos commentaires:

#!/bin/bash
pathMontage="/media/folder"

result=$(eval "mount | grep " ${pathMontage} " | wc -l")
if [ "$result" = "1" ];then
        echo "montage effectif"
else
        echo "montage not work"
fi
  • # Paliatif

    Posté par  (site web personnel) . Évalué à 3.

    Ça ne répond pas à ta question, mais ça peut répondre à ton problème, tu peux utiliser:

    mountpoint $mountPoint
    if [ $? -eq 0 ]; thenfi

    Sinon, pas testé, une idée de piste pour ta question, construire l'expression hors du sous-shell:

    monexpr="mount | grep \"${mountPoint}\" | wc -l"
    result=$($monexpr)

    Peut-être creuser vers http://tldp.org/LDP/abs/html/subshells.html

    Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

    • [^] # Re: Paliatif

      Posté par  . Évalué à 2. Dernière modification le 25 mai 2017 à 19:47.

      Ça ne répond pas à ta question, mais ça peut répondre à ton problème, tu peux utiliser:

      Ta méthode fonctionne merci. Avec l'ajout de >/dev/null 2>&1 on peut aussi supprimer la phrase de réponse sans apporter de bug :)

      mountpoint $mountPoint >/dev/null 2>&1
      if [ $? -eq 0 ]; thenfi

      Par contre la seconde méthode lance la commande plus tôt que de l'enregistrer dans la variable (mount me renvoie son help ^ ^ )

      Note pour ceux qui vont tomber sur ce thread via google : je n'ai pas encore testé en montant le dossier distant puis en le rendant inaccessible sans le démonter (exemple couper le réseau)

      Donation Bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

      • [^] # Re: Paliatif

        Posté par  . Évalué à 5.

        Ta méthode fonctionne merci. Avec l'ajout de >/dev/null 2>&1 on peut aussi supprimer la phrase de réponse sans apporter de bug :)

        Ou alors on demande à mountpoint de ne rien afficher avec son option --quiet

        • [^] # Re: Paliatif

          Posté par  . Évalué à 1.

          C'est beaucoup plus propre en effet ^ ^

          Donation Bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

  • # Salut

    Posté par  . Évalué à 1. Dernière modification le 25 mai 2017 à 20:16.

    Pas besoin de variable 'result', il vaut mieux utiliser $? comme déjà dit. Si tu n’as pas la commande mountpoint tu peux faire :

    #!/usr/bin/env bash
    
    mount |grep -q "$1"
    
    if [ $? -eq 0 ]
    
     then echo "Montage $1 effectif"
    
     else echo "Montage $1 absent"
    
    fi

    ça donne :

    $ ./hop.sh /xxxxxx
    Montage /xxxxxx absent
    $ ./hop.sh /sys
    Montage /sys effectif
    
    • [^] # Re: Salut

      Posté par  . Évalué à 2.

      Je précise que ce script n’est pas très robuste, on aurait grandement intérêt à être plus précis dans ce qui est greppé, par exemple :

      mount |grep -q " $1 "

      parce que sinon, en cherchant à vérifier '/var' on aurait aussi un résultat positif si /var n’est pas monté mais /var/run l’est…

      • [^] # Re: Salut

        Posté par  . Évalué à 1.

        Merci pour l'astuce avec grep.
        Quant a l’utilisation de result, j'avais tapé la commande directement dans le if et le terminal me renvoyait la même erreur.
        Le problème semble venir de l'utilisation de variable dans $(commande).
        Vu qu'il m'arrive de temps en temps de vouloir utiliser ce genre de commande dans des scripts, savoir comment faire m’intéresse :)

        Donation Bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

        • [^] # Re: Salut

          Posté par  (site web personnel, Mastodon) . Évalué à 2.

          Hello,

          Si je me souviens bien, l'astuce est que $() ouvre un nouveau shell avec ses propres variables. Du coup, pour lui la valeur de la variable est vide.

          Si tu veux pouvoir passer des paramètres à un shell exécuté ainsi, je tenterai de passer par les variables d'environnement grâce à la commande export depuis le script de base, puis d'employer la variable d'environnement dans le shell créé.

      • [^] # Re: Salut

        Posté par  (site web personnel) . Évalué à 5.

        Perso, je fais encore plus cours dans mes scripts

        if mount | grep -q "$1"
        then
        echo "Montage $1 effectif"
        else
        echo "Montage $1 absent"
        fi

  • # Sinon

    Posté par  (site web personnel) . Évalué à 4.

    A savoir

    if [ ${result} = "1" ];then
    Bof bof car si ${result} est vide, tu est marron… Toujours mettre des guillemets. Par ailleurs, "wc -l" renvoi toujours une entier donc tu peux faire un test sur les entiers.

     if [ "${result}" -eq 1 ];then
    

    Ou par exemple autoriser un résultat supérieur à 1….

    if [ "${result}" -gt 0 ];then
    Quand à ton cas ci dessus, toujours faire un export de $mountPoint pour les sous shell. Cela résout pas mal de soucis.

    • [^] # Re: Sinon

      Posté par  . Évalué à 2.

      Vu qu'il utilise explicitement bash (pas besoin d'être compatible bourne shell), autant utiliser la syntaxe

      if [[ $result == 1 ]] ;then

      comme [[ est une construction du langage (contrairement à [ qui est une commande), il n'a pas ce problème.

  • # .

    Posté par  . Évalué à 1.

    Cela m'intrigue car tous vos examples devraient fonctionner.
    Les variables (exportées ou non), les fonctions et alias du parent sont accessibles dans le sous-shell.

    Peut-être une erreur de retranscription du nom d'une variable ?
    Lancez un trace sur les examples qui ne fonctionnent pas chez vous (bash -x)

    • [^] # Re: .

      Posté par  (site web personnel) . Évalué à 3.

      Non, les alias ne sont pas accessible dans les sous shell et à ma connaissance, il n'est pas possible de les exporter (contrairement aux fonctions). D'ailleurs, je ne sais pas pourquoi de nos jours les alias ne sont pas juste une syntaxe simplifiée pour déclarer une fonction.

      • [^] # Re: .

        Posté par  . Évalué à 1.

        Je vous assure que si. Un sous-shell est un simple fork qui hérite de la quasi-totalité de l'environnement (à l'exception des traps sinon ce serait le bordel) du parent. Un sous-shell est créé via $(), (), | et & de mémoire.

        Si vous invoquez le shell directement (sh -c "…"), évidemment cela ne marche plus et dans le meilleur des cas seules les variables d'environnements seront passées à l'enfant. Pour l'export de fonctions, j'en ai jamais entendu parler. (J'utilise dash et ksh).

  • # utiliser eval ?

    Posté par  . Évalué à 3.

    • [^] # Re: utiliser eval ?

      Posté par  . Évalué à 1.

      Je viens de tester avec le code suivant et ça fonctionne

      FONCTIONNE

      #!/bin/bash
      
      monPath="/media/cloud"
      
      su pi -c "mount $monPath"
      
      result=$(eval "mount | grep ${monPath} | wc -l")
      if [ $result = "1" ];then
              echo "montage effectif"
      else
              echo "montage not work"
      fi
      
      su pi -c "umount $monPath"

      NE FONCTIONNE PAS

      #!/bin/bash
      
      monPath="/media/cloud"
      
      su pi -c "mount $monPath"
      
      eval "mount | grep ${monPath} | wc -l"
      if [ $? = "1" ];then
              echo "montage effectif"
      else
              echo "montage not work"
      fi
      
      su pi -c "umount $monPath"

      Donation Bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

      • [^] # Re: utiliser eval ?

        Posté par  . Évalué à 3.

        Pourquoi mests-tru la commande à lancer entre double quotes ?

        • [^] # Re: utiliser eval ?

          Posté par  . Évalué à 1. Dernière modification le 26 mai 2017 à 13:58.

          Ah, mauvaise habitude de ma part ^ ^
          Je pensais qu'il fallait toujours les double quotes pour que les variables fonctionnent bien avec bash ^ ^ Mais tu as raison, sans ça fonctionne aussi bien :)

          Donation Bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

          • [^] # Re: utiliser eval ?

            Posté par  . Évalué à 3.

            C'est pas forcément mauvais, mais il y a des cas ou ça ne marche pas.

            Exemple :

            $touch abc def ghi
            $ls -l
            total 0
            -rw-rw-r-- 1 xxxx xxxx 0 May 26 14:14 abc
            -rw-rw-r-- 1 xxxx xxxx 0 May 26 14:14 def
            -rw-rw-r-- 1 xxxx xxxx 0 May 26 14:14 ghi
            $"ls -l"
            -bash: ls -l: command not found
      • [^] # Re: utiliser eval ?

        Posté par  . Évalué à 3.

        Tu ne fais pas le bon test …
        Tu testes dans le premier cas la chaine retournée par la commande wc -l qui te retourne 1 (le nombre de lignes dans lequel ton montage apparaît), et dans un second cas le code retour de la commande qui correspond à la bonne exécution ou non de ta commande. En shell, le code retour d'une commande qui s'exécute bien est 0. Donc dans le second cas, tu auras un code retour de 0 qui ne correspondra pas au nombre de fs montés, mais au fait que ta commande s'est bien exécutée. Même si tu avais 2 ou 3 lignes qui correspondent à ton pattern, tu aurais toujours un code retour de 0 car en bash, un code retour de 0 signifie que la commande s'est bien exécutée, qu'il n'y a pas eu d'erreur. Exemple :

        exemple 1:

        $ echo "abc
        --- def
        --- fgh
        --- " | wc -l
        4
        $ echo "$?"
        0

        exemple 2:

        $wc -l ""
        wc: invalid zero-length file name
        $echo $?
        1
  • # Chez moi ça marche...

    Posté par  (site web personnel) . Évalué à 3.

    Ton code est semble-t-il tout à fait correct, et en l'essayant, je n'ai aucune erreur.

        #!/bin/bash
    
        mountPoint="/media/monPath"
        result=$(mount | grep "$mountPoint" | wc -l)
        if [ ${result} = "1" ];then
                echo "montage effectif"
        else
                echo "montage not work"
        fi

    Ce que personnellement, j'aurais fait (puisque Bash) :

        #!/bin/bash
        mountPoint="/media/monPath"
        mount | grep -q " ${mountPoint}" || { printf '%s' "Mount NOK"; exit 1; }
        printf '%s' "Mount OK"

    Ou bien sans utiliser mount :

        #!/bin/bash
        mountPoint="/media/monPath"
        grep -q " ${mountPoint}" /etc/mtab || { printf '%s' "Mount NOK"; exit 1; }
        printf '%s' "Mount OK"
    • [^] # Re: Chez moi ça marche...

      Posté par  . Évalué à 1. Dernière modification le 26 mai 2017 à 13:36.

      Ou bien sans utiliser mount

      merci pour l'astuce, je vais tester. Je suis en train de répertorier toutes les méthodes que je trouve pour checker les points de montage :)

      Le but n'est bien entendu pas d'afficher si le montage fonctionne ou non mais de pouvoir stopper/reporter mes scripts d'export de données (logs et backup entre autre) si le montage ne fonctionne pas :)

      Il me reste a vérifier comment se comporte toutes les solutions citées dans ce thread si je monte un dossier puis coupe le réseau (par exemple la méthode via test d'existence d'un dossier se met en attente et nécessite donc un timer pour ne pas marcher sur les plates bandes d'une nouvelle instance lancée par cron )

      Donation Bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

    • [^] # Re: Chez moi ça marche...

      Posté par  . Évalué à 1.

      Je n'arrive pas à caser le grep -q " ${mountPoint}" /etc/mtab dans une condition, ni a afficher se qu'elle produit comme sortie en l'entrant directement dans le terminal (dans ce dernier elle ne renvoie rien, que le dossier soit monté ou non).
      Par contre telle quelle ton script fonctionne.

      Donation Bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

      • [^] # Re: Chez moi ça marche...

        Posté par  . Évalué à 1.

        Il y a un espace en trop

        • [^] # Re: Chez moi ça marche...

          Posté par  . Évalué à 1.

          Le problème ne vient pas de là :) L'espace est là pour améliorer le grep (voir le commentaire de Marotte ci-haut)

          Donation Bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

          • [^] # Re: Chez moi ça marche...

            Posté par  . Évalué à 2.

            Ah ok;
            Fait un trace alors, c'est un bon moyen de savoir ce qui se passe (et ce qui ne se passe pas) ;)

            • [^] # Re: Chez moi ça marche...

              Posté par  . Évalué à 1. Dernière modification le 26 mai 2017 à 15:35.

              Merci, problème résolu ! (merci a stackoverflow aussi mdr)

              #!/bin/bash
              
              monPath="/media/cloud"
              
              su pi -c "mount $monPath"
              
              grep -q " ${monPath}" /etc/mtab
              if [ $? = "0" ];then
                      echo "montage effectif"
              else
                      echo "montage not work"
              fi
              
              su pi -c "umount $monPath"

              grep -q " ${monPath}" /etc/mtab renvoie 0 quand c'est bon et 1 quand c'est pas bon (comme expliqué par totof2000 ci-haut d'ailleurs ^ ^ )

              Donation Bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

              • [^] # Re: Chez moi ça marche...

                Posté par  (site web personnel) . Évalué à 2.

                if [ $? = "0" ];then

                Mais non de dieu, tu vas arrêter ça tout de suite !

                $? est un numérique et "0" est une chaine.

                Soit tu utilises :

                if [ $? -eq 0 ];then

                Soit tu préfères un truc moche :

                if [ "$?" = "0" ];then

                Mais pas ton horreur !

                Après tu peux aussi simplifier :

                if grep -q " ${monPath}" /etc/mtab; then
      • [^] # Re: Chez moi ça marche...

        Posté par  (site web personnel) . Évalué à 3.

        ni a afficher se qu'elle produit

        man grep et cherches à quoi sert le -q

  • # Ouille Ca pique !!!!

    Posté par  . Évalué à 4.

    Le T au bout du tag RESOLU dans le titre, c'est affreux.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.