Forum Programmation.shell ajouter une entrée fstab en bash

Posté par  . Licence CC By‑SA.
3
30
juil.
2015

Bonjour,

Je dois ajouter une entrée de fstab sur 70 postes de dev;
Hélas je ne dispose pas d'outils comme puppet.
J'ai donc décidé de faire un script bash que j'enverrai aux développeurs qui l’exécuteront de la façon suivante: sudo ./scriptfs.sh
Cependant étant moins compétant sur Linux que sur Windows et ne maitrisant pas la programmation bash je sollicite votre aide pour améliorer/corriger le simulacre de script que j'ai gribouillé.
De plus je n'ai ni vm ni poste linux de test. Les postes cibles sont des Debian7/8 et ubuntu 12.04.
Voici mon tout premier hello world rn bash:

    #!/bin/bash

    cp -p /etc/fstab /etc/fstab.back-$(date +%F)

    dir_src=//fileserver/share
    dir_tgt=/mount/share
    fsoptions="cifs _netdev,users,rw,auto,users,credentials=/etc/.cifspasswd,iocharset=utf8,file_mode=0777,dir_mode=0777 0 0"

    mkdir -p $dir_tgt


    echo -e "$dir_src \t\t $dir_tgt \t\t $fsoptions" >> /etc/fstab

    printf "put your windows login: \n"
    read login
    echo -e "username=$login" >> /etc/.cifspasswd
    printf "\n"
    printf "Now put your windows password: \n"
    read password
    echo "password=$password" >> /etc/.cifspasswd
    echo "domain=dom.local" >> /etc/.cifspasswd

    chmod 600 /etc/.cifspasswd

    mount -a >> /tmp/mount.log

    if [ $? -ne 0]
    then

    chown -R `whoami`  $dir_tgt
    cat /tmp/mount.log | mail -s " $hostname $username fstab return " -a "FROM:$username@mycompany.com" it@mycompany.com

    else

    echo " all work fine " | mail -s " fstab ok " -a "FROM:$username@mycompany.com" it@mycompany.com


    fi

Merci à tous pour votre aide et vos précieux conseils

  • # man bash

    Posté par  . Évalué à 3.

    juste un petit read -s pour le mot de passe.
    pas indispensable, mais ça fait plus sérieux.

    • [^] # Re: man bash

      Posté par  . Évalué à 1.

      Ok merci
      C'est tout ? J'ai pas d'environnement sans risque pour tester. Vous ne voyez rien qui puisse ne pas fonctionner?
      C'est mon premier hello world.

      • [^] # Re: man bash

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

        impossible à dire sans exécuter le script sur une cible, dans un environnement réel
        Parfois, on a des surprises.

        Système - Réseau - Sécurité Open Source

  • # $hostname $username

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

    Bonjour,

    Il me semble que les variables $hostname $username ne sont pas définies dans ton script, est ce volontaire pour le script que tu as envoyé ici ?

    De plus, la syntaxe whoami serait plus à remplacer par $(whoami).

    Pour la simplicité de lecture, il est bon aussi d'ajouter de l'indentation entre le then , le else et le fi… mais c'est du détail.

    Dans ton script, je ne comprend pas trop l'intéret de la commande chown apres le then… mais tu dois avoir une bonne raison ;o)

    Si tu ne connais pas, je te conseille de te référer à ABS en français), c'est pour moi une référence.

    Et pour un premier script, bravo, c'est plutôt pas mal ;o)

    Denis

    • [^] # Re: $hostname $username

      Posté par  . Évalué à 1.

      Merci,

      pour les deux variables $hostname et $username je pensais que c'était des variables d'environnement existantes mais après vérification elles n'existent pas.

      pour le whoami je vais faire comme tu as dit.

      le chown se trouve ici pour que ce soit fait après le montage pour être sur que les droits seront bien appliqués sur l'ensemble de l'arborescence.

      Oui c'est mon premier script… en bash en tout cas. d'habitude je script sur windows en vbs ou powershell. Donc c'est l'occasion d'apprendre un autre langage.
      C'est en étant confronté à ce genre de situation qu'on apprend, sinon le reste du temps quand on en a pas un besoin immédiat on apprend jamais.

      Merci encore pour tes conseils

  • # quelques remarques

    Posté par  . Évalué à 3. Dernière modification le 31 juillet 2015 à 13:50.

    Le

    chown -R `whoami`  $dir_tgt

    est inutile, c'est toi qui a créé ce répertoire un peu avant, donc il t'appartient déjà.
    De toute façon, si le script n'est pas exécuté par root il n'aura pas le droit de changer le propriétaire (et faire le reste non plus d'ailleurs).
    Si le but est de le remettre à root au cas où il existerait déjà avant, met explicitement root à la commande chown.
    Au passage, la syntaxe en backtick est dépréciée, il est préférable d'utiliser la version $() qui a l'avantage d'être imbriquable.
    Mais de toute façon, le mount peut échouer pour d'autres raisons, et tu pourrais aussi bien faire ce chown tout de suite après la tentative de création du répertoire.

    La commande interne read a une option -p pour afficher un prompt, ça économise le printf avant.

    Tu devrais toujours utiliser des double quotes autours de tes variables ($dir_tgt en l'occurrence), ce n'est pas un problème dans ton exemple car la variable ne contient rien de problématique, mais si tu modifie ultérieurement la valeur ça pourrait le de venir.0A;
    Ce n'est pas une bonne idée d'utiliser un fichier temporaire avec un nom fixe (surtout dans un répertoire commun et avec un nom aussi générique).
    Mieux vaut utiliser la commande mktemp pour générer un fichier temporaire avec un nom aléatoire, et ne pas oublier de le supprimer à la fin.
    Au passage, utiliser la redirection de type >> signifie que tu ajoute à la fin du fichier, ça ne me semble pas le but ici. (ou alors voudrais-tu que le log s'accumule à chaque exécution du script?)

    MOUNTLOG=$(mktemp mount.XXXXXX)
    mount -a > "$MOUNTLOG"
    #..suite
    rm -f "$MOUNTLOG"

    Plutôt que de tester le code de sortie de la commande mount, tu peux la mettre directement dans le if:

    if ! mount -a > "$MOUNTLOG" ;then

    (d'ailleurs il manquait un espace entre le 0 et le ])

    Tu utilise la commande mail, es-tu sur qu'il y aura toujours un serveur mail correctement configuré sur tous les serveurs où le script sera utilisé? (ou au minimum une implémentation locale de sendmail, comme dma ou ssmtp)
    Et puis, ce serait quand même bien d'informer la personne qui exécute le script si ça s'est passé correctement ou non.

    Pour finir, c'est une très mauvaise idée d'écrire un script complexe ex nihilo et de l'exécuter directement sur des machines de production. Mieux vaut le tester d'abord sur une machine qu'il est acceptable de casser un peu.
    Prépare-toi à devoir intervenir en urgence sur certaines machines qui ne fonctionneraient plus.

    • [^] # Re: quelques remarques

      Posté par  . Évalué à 1. Dernière modification le 12 août 2015 à 13:11.

      Merci wismerhill pour tes nombreux conseils

      chown -R inutile : ok je note
      pour /etc/.cifspasswd : je remplace par "$HOME"/.cifspasswd
      le fichier de log : oui le > n'est utile en effet, de plus je vais l'orienter vers $HOME/mount.log
      pour la commande mail: oui il y a un exim4 sur chaque poste
      Je viens de trouver un poste de test sur lequel je vais faire mes tests.

      voici la nouvelle version de mon script qui j'espère tient compte de toutes vos remarques:

          #!/bin/bash
      
          hostname="$(cat /etc/hostname)"
          username="$(whoami)"
          mountlog="$HOME"/mount.log"
          cp -p /etc/fstab /etc/fstab.back-"$(date +%F)"
      
          dir_src="//fileserver/share"
          dir_tgt="/mount/share"
          fsoptions="cifs _netdev,users,rw,auto,users,credentials="$HOME"/.cifspasswd,iocharset=utf8,file_mode=0777,dir_mode=0777 0 0"
      
          mkdir -p "$dir_tgt"
      
      
          echo -e "$dir_src" \t "$dir_tgt" \t "$fsoptions" >> /etc/fstab
      
          printf "put your windows login: \n"
          read login
          echo -e username="$login" >> "$HOME"/.cifspasswd
          printf "\n"
          printf "Now put your windows password: \n"
          read -s password
          echo password="$password" >> "$HOME"/.cifspasswd
          echo "domain=dom.local" >> "$HOME"/.cifspasswd
      
          chmod 600 "$HOME"/.cifspasswd
      
          if ! mount -a > "$mountlog"
          then
      
          cat "$mountlog" | mail -s " $hostname $username fstab return " -a "FROM:$username@mycompany.com" it@mycompany.com
      
          else
      
          echo " all work fine " | mail -s " fstab ok " -a "FROM:$username@mycompany.com" it@mycompany.com
      
          fi

      Désolé je ne sais pas comment activer la coloration syntaxique dans mon post

      • [^] # Re: quelques remarques

        Posté par  . Évalué à 2.

        Encore une fois, un script qui veut modifier /etc/fstab ne peut fonctionner qu'en root, donc récupérer le nom de l'utilisateur avec whoami est inutile, ce sera forcément root. (à moins que tes postes aient des configurations spéciales?)

        Concernant le hostname, bash défini déjà lui-même une variable HOSTNAME (à de très rares exceptions près, les variables pré-définies sont en majuscule).

        Pour les options de montage, les file_mode et dir_mode que tu met sont une mauvaise idée, ça veut dire que tout le monde peut écrire/supprimer n'importe quoi dans le montage, et que tous les fichiers seront exécutables. Peut-être est-ce vraiment ce que tu veux, mais ne perd pas de vue que ça veut dire que tous les utilisateurs locaux font ce qu'ils veulent.
        Il serait préférable d'utiliser les valeurs file_mode=0664,dir_mode=0775 combinées avec l'options gid pour que seuls les utilisateurs du groupe donné aient accès en écriture.
        (et tu as mis deux fois l'options users)

        C'était également une meilleure idée de mettre le fichier credentials dans /etc (sans le point au début, pas besoin qu'il soit caché), car maintenant il va se retrouver dans le home de root, ou pire, si l'utilisateur qui exécute le script ne le fait pas correctement (par exemple avec "su" plutôt que "su -"), ça peut se retrouver dans le home de l'utilisateur normal.
        (par contre, le "chmod 600" est bien ce qu'on veut pour ce fichier)

        Toujours pas envie d'informer l'utilisateur qui exécute le script si ça s'est passé correctement?

        Pour la coloration syntaxique, c'est indiqué dans l'aide-mémoire de la page d'édition (et il faut laisser une ligne avant et après, sinon ça ne fait rien du tout)

      • [^] # Re: quelques remarques

        Posté par  . Évalué à 1. Dernière modification le 12 août 2015 à 13:12.

        Si tu as mailx tu peux remplacer "-a FROM" par -r .
        Comme précisé précédemment $USERNAME est root a priori mais je laisse la variable au cas où.
        Mettre la date à ton fichier est hasardeux car tu as déjà l'information et tu risques d'écraser les précédentes tentatives. Voir l'option "cp -b -S" pour un usage plus poussé

                #!/bin/bash
        
                # Exit immédiatement si quelque chose de non prévu arrive. ça peut éviter un effet boule de neige
                set -e
        
                CIFS_FILE=$HOME/.cifspasswd
                MOUNT_LOG=/tmp/mount.log
                USERNAME=$(id -un)
                HOSTNAME=$(hostname -f)
                FS_MOUNTS="//fileserver/share\t/mount/share"
        
                _mail () {
                    cat $MOUNT_LOG | mail -s "[$HOSTNAME] $USERNAME: $1" -r "$USERNAME@mycompany.com" it@mycompany.com
                }
        
                read -p "Put your windows login? " login
                read -s -p "Now put your windows password (*hidden*)? " password
        
                # Vérifie les droits de création
                touch $CIFS_FILE
                chmod 600 $CIFS_FILE
        
                # Ecrase le ficher s'il existe (n'ajoute pas à la fin)
                echo -e "username=$login\npassword=$password\ndomain=dom.local" > $CIFS_FILE
        
                # L'option -u t'évitera d'écraser ta sauvegarde
                cp -u -p -b -S "_$(date +%F)" fstab fstab.back
        
                # Créé un bloc de texte à copier (plus simple à adapter au besoin)
                cat <<EOD >>/tmp/fstab
                # ADDED BY $0 ($(date))
                $FS_MOUNTS\tcifs\t_netdev,users,rw,auto,users,credentials=$CIFS_FILE,iocharset=utf8,file_mode=0777,dir_mode=0777 0 0"
                # END
                EOD
        
                # Crée les répertoires en remplaçant d'abord la tabulation en espace pour la commande mkdir
                mkdir -p $(tr "\t" " " <<<$FS_MOUNTS)
        
                # Envoie le résultat par mail
                if ! mount -va > $MOUNT_LOG
                then
                    _mail "FSTAB ERROR"
                else
                    _mail "fstab ok"
                fi
        
                # On garde la trace de la dernière exécution dans /tmp au cas où...
                # ... sinon rm -f $MOUNT_LOG
  • # RemoteScript

    Posté par  . Évalué à 1.

    Salut
    Je me permet de te suggérer RemoteScript qui te permet d'éxecuter tes scripts en asynchrone sur autant de machines que tu le souhaite, même si elles sont éteintes.
    Ça tourne sur un serveur Lamp avec libssh-2.

    http://sourceforge.net/projects/remotescript/
    a+!

  • # Merci à tous pour votre aide

    Posté par  . Évalué à 1.

    Je vais essayer de m'inspirer de tous vos conseils

  • # Erreur durant le read login :» : identifiant non valable login + fin de fichier prématurée

    Posté par  . Évalué à 1. Dernière modification le 12 août 2015 à 13:12.

    Salut à tous,

    Je reviens avec mon script. Finalement j'ai changé de stratégie suite au commentaire de wismerhill qui disait que seul root peut écrire dans le fstab.
    Il ne s'agit donc plus d'écrire dans le fstab mais dans "$HOME"/.bashrc.
    J'ai donc revue mon script que voici mais il me reste une erreur au moment du read + une autre juste avant le fi(voir ci dessous le script).

        #!/bin/bash
        cat /dev/null > $HOME/.cifspasswd
        hostname="$(cat /etc/hostname)"
        username="$(whoami)"
        dir_src="//mycorp.lan/share"
        dir_tgt="$HOME/securise"
        mkdir -p "$dir_tgt"
        chown -R "$(whoami)" "$dir_tgt"
        chmod 700 "$dir_tgt"
        printf "\n"
        echo -n "put your windows login and press [ENTER]:"
        read  login
        echo -e "username=$login" >> "$HOME"/.cifspasswd""
        printf "\n"
        echo -n "Now put your windows password and press [ENTER]:"
        read -s password
        printf "\n"
        echo -e "password="$password"" >> "$HOME"/.cifspasswd""
        echo "domain=mycorp.lan" >> "$HOME"/.cifspasswd""
        chmod 600 "$HOME"/.cifspasswd""
        if grep -i "mount -t cifs" "$HOME"/.bashrc"" ; then
        printf "\n"
        else
        echo -e "mount -t cifs $dir_src $dir_tgt -o credentials=$HOME/.cifspasswd" >> "$HOME"/.bashrc""
        fi
        . ~/.bashrc
        ls -l "$dir_tgt" | wc -l
        if [ "$?" -eq 0 ]
        then
        echo "pb mount" | mail -s  "$hostname $username" " mount error " -a FROM:"$(whoami)@mycorp.fr it@mycorp.fr"
        else
        echo " all work fine " | mail -s " mount ok " -a FROM:"$(whoami)@mycorp.fr  it@mycorp.fr"
        fi
    
    
    
    
    
    Voici l'erreur:
    admin@debian7:~$ bash -x Filer.sh
    + cat /dev/null
    ++ cat /etc/hostname
    + hostname=$'debian7\r'
    ++ whoami
    + username=$'admin\r'
    + dir_src=$'//mycorp.lan/share\r'
    + dir_tgt=$'/home/admin/securise\r'
    + mkdir -p $'/home/admin/securise\r\r'
    ++ whoami
    + chown -R admin $'/home/admin/securise\r\r'
    + chmod 700 $'/home/admin/securise\r\r'
    ' printf '\n
    
    ' echo -n 'put your windows login and press [ENTER]:
    + read $'login\r'login and press [ENTER]:
    georges.orwell
     » : identifiant non valable login
    + echo -e username=
    ' printf '\n
    
    ' echo -n 'Now put your windows password and press [ENTER]:
    + read -s $'password\r'ssword and press [ENTER]:
     » : identifiant non valable password
    ' printf '\n
    
    + echo -e password=
    + echo domain=mycorp.lan
    + chmod 600 $'/home/admin/.cifspasswd\r'
    Filer.sh: ligne34: Erreur de syntaxe : fin de fichier prématurée

    SOS HELP svp je galère depuis hier dessus

  • # moche

    Posté par  . Évalué à 3.

    c'est moche de demander aux gens de saisir leur login/pass pour ecrire ensuite une ligne dans le fstab pour donner les droits complets à ce dossier (777)
    autant ne pas mettre le login/pass sur le partage

    ensuite les navigateurs de fichiers sont là pour ca, et permettent de faire des bookmarks des dossiers.
    ils permettent à plusieurs utilisateurs de partager leur machine, sans pour autant acceder aux memes données dans le partage

    c'est plus propre.

    sinon dans ton script, tu mets 2x users dans les options de montage

Suivre le flux des commentaires

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