web-dev-qa-db-fra.com

Le script Bash utilisant la sortie de mount en tant que variable génère de nombreuses erreurs

Serveur Ubuntu 18.04 + LXDE. Je ne peux pas comprendre ce script bash.
Voici mon script "start" (avec numérotation des lignes):

#!/bin/bash
reply=Sudo mount 192.168.0.2:/home/dk/NFS /home/dk/NFS
if $reply == 0
then 
    echo "NFS mounted OK"
else 
    echo "Mounting NFS failed: $reply"
fi

reply=Sudo mount LABEL="60GB" /home/dk/60GB
if $reply == 0
then 
    echo "60GB mounted OK"
else 
    echo "Mounting 60GB failed: $reply"
fi
exit 0

C'est le résultat de l'exécuter:

$ ./scripts/start
mount: only root can do that
./start: line 3: ==: command not found
Mounting NFS failed: 
mount: only root can do that
./start: line 11: ==: command not found
Mounting 60GB failed: 
$ 
  • Pourquoi a-t-il ignoré le Sudo avant le mount?
  • Pourquoi n'a-t-il pas considéré if comme une commande?
  • Pourquoi n'a-t-il pas imprimé la valeur (non nulle) de $reply?
4
Dave Kimble

Eh bien, vous n'attribuez pas correctement la sortie d'une commande. Devrait être:

reply=$(Sudo mount 192.168.0.2:/home/dk/NFS /home/dk/NFS)

Cela s'appelle substitution de commande. Parfois, vous le voyez dans l'ancienne syntaxe Bourne Shell avec des guillemets arrières au lieu de $(...), mais ce n'est plus recommandé de nos jours car les guillemets arrières ne peuvent pas être imbriqués facilement, alors que vous pouvez imbriquer $( cmd1 $(cmd2)).

Pourquoi n'a-t-il pas considéré le "si" comme une commande?

Si les instructions fonctionnent avec des commandes, mais que vous donnez la variable $reply, qui n'existe que temporairement (voir réponse plus loin dans cette réponse), elle n'existe donc que pour l'environnement de la commande mountname__, mais le shell qui exécute le script n'en sait rien - il n'en a rien. t existent. Pour comparer les chaînes, utilisez [, et oui, cette commande est également appelée testname__. Alors faites

if test "$reply" == 0

Voir les citations? C'est important, sinon, s'il y a des espaces, Shell étendra la variable à deux ou plusieurs entités distinctes et non à une seule.

Mais si vous voulez vérifier le statut de sortie de la commande, il suffit de faire

if mount 192.168.0.2:/home/dk/NFS /home/dk/NFS

Voir non Sudoname__? En effet, il est généralement redondant d’utiliser plusieurs fois Sudo dans un script. Appelez simplement le script lui-même avec Sudo et toutes les commandes auront le privilège root.

Je dirais aussi que echo est redondant car la commande mount peut déjà imprimer des erreurs sur le terminal, mais si vous voulez un message personnalisé, vous pouvez le faire.

if mount 192.168.0.2:/home/dk/NFS /home/dk/NFS 1> /dev/null
then
       echo "Success"
else
       echo "Fail"
fi

En raison de 1>, la sortie normale est supprimée (en fait redirigée vers /dev/null surtout à cette fin), mais des erreurs s'afficheront si quelque chose ne va pas.

Pourquoi a-t-il ignoré le "Sudo" avant le "montage"?

En ce qui concerne la raison pour laquelle vous obtenez un message d'erreur, c'est parce que le formulaire

reply=Sudo mount 192.168.0.2:/home/dk/NFS /home/dk/NFS

est traité comme envvariable=value command arg1 arg2, c’est-à-dire que vous mettez la variable resultavec la valeur Sudodans l’environnement de la commande mountname__. La commande le saura, mais une fois la commande terminée, la variable sera également partie.

Pourquoi n'a-t-il pas imprimé la valeur (non nulle) de $ réponse?

Parce que replyne stocke pas le statut de sortie comme expliqué précédemment. Il y a en fait une variable pour celle fournie par Shell déjà, $? alors utilisez-la comme

if [ $? -eq 0 ] 

Rincez et répétez les suggestions relatives aux autres instructions de votre script.

Bonne chance

11

En plus de la bonne réponse de Sergiy, vous pouvez envisager d'utiliser les listes AND et OR pour vérifier rapidement si une commande renvoie un état de sortie égal à zéro (réussi) ou non, par exemple

command && echo "command succeeded" || echo "command failed"

Voici un extrait de man bash:

Les listes AND et OR sont des séquences d'un ou de plusieurs pipelines séparés par les opérateurs de contrôle && et ||, respectivement. Les listes AND et OR sont exécutées avec une associativité à gauche. Une liste AND a la forme

      command1 && command2

commande2 est exécutée si, et seulement si, commande1 renvoie un état de sortie égal à zéro.

Une liste OR a la forme

      command1 || command2

commande2 est exécutée si et seulement si commande1 renvoie un état de sortie différent de zéro. Le statut de retour des listes AND et OR correspond au statut de sortie de la dernière commande exécutée dans la liste.

Vous pouvez les combiner et également voir le statut de sortie si vous le souhaitez, avec votre exemple tel que:

Sudo mount 192.168.0.2:/home/dk/NFS /home/dk/NFS && \
echo "NFS mounted OK" || echo "Mounting NFS failed: $?"
7
Xen2050

Problèmes avec votre script:

  • Vous avez manqué ` pour la commande Sudo mount ... Pour exécuter une commande, vous devez la remettre entre guillemets `command` ou $(command). Vous pouvez également capturer la valeur de retour du script en utilisant $?.
  • Si la construction de la boucle était incorrecte

    if [ $var -eq/-lt/-gt "string"/number ]
    then
    echo "...."
    else
    echo "..."
    fi; <=== Most users miss this.
    

** Script édité **

#!/bin/bash

reply=`Sudo mount 192.168.0.2:/home/dk/NFS /home/dk/NFS`

if [ $reply -eq "0" ]
then 
echo "NFS mounted OK"
else 
echo "Mounting NFS failed: $reply"
fi;

reply=`Sudo mount LABEL="60GB" /home/dk/60GB`
if[ $reply -eq "0" ]
then 
    echo "60GB mounted OK"
else 
    echo "Mounting 60GB failed: $reply"
fi;
exit 0
0
user3409057