Comment monter sshfs au démarrage?

12

En utilisant un boîtier NAS comme serveur de fichiers 24/7, j'aimerais utiliser sshfs pour y accéder à partir d'un bureau Ubuntu 9.04. Actuellement, j'ai cette ligne dans le fstab du bureau:

sshfs#jldugger@storage:/mnt/HD_a2/    /mnt/storage    fuse   comment=sshfs,auto,users,exec,uid=1000,gid=1000,allow_other,reconnect,transform_symlinks,BatchMode=yes,fsname=sshfs#jldugger@storage/mnt/HD_a2/ 0 0

Je peux confirmer que cela fonctionne avec le support /mnt/storage. Ce dont j'ai besoin, c'est d'une méthode de montage au démarrage, mais une fois la connexion réseau établie.

jldugger
la source
Comment avez-vous configuré l'authentification? Êtes-vous invité à entrer un mot de passe lorsque vous le montez manuellement?
Zoredache
Authentification par paire. Pas le plus sûr, mais probablement suffisant.
jldugger

Réponses:

8

Actuellement, Upstart dans Ubuntu ne génère pas d'événements réseau. Au lieu de cela, il appelle sysvinit traditionnel. Par défaut, NetworkManager est installé et en cours d'exécution; plutôt que d'émettre des événements de réseau pour démarrer, il contient un répartiteur de run-parts (/etc/NetworkManager/dispatcher.d/) qui lui-même s'appuie simplement sur le répartiteur de run-parts d'ifupdown (/etc/network/*.d/). En particulier, vous vous souciez de /etc/network/if-up.d/ et /etc/network/if-down.d/

Configurez d'abord une paire de clés ssh non chiffrée, afin de pouvoir monter le point sans invite. Écrivez un script, placez-le dans /etc/network/if-up.d/ et rendez exécutable. Ce qui suit a été découvert sur UbuntuForums et me suffisait:

#!/bin/sh
## http://ubuntuforums.org/showthread.php?t=430312
## The script will attempt to mount any fstab entry with an option
## "...,comment=$SELECTED_STRING,..."
## Use this to select specific sshfs mounts rather than all of them.
SELECTED_STRING="sshfs"

# Not for loopback
[ "$IFACE" != "lo" ] || exit 0

## define a number of useful functions

## returns true if input contains nothing but the digits 0-9, false otherwise
## so realy, more like isa_positive_integer 
isa_number () {
    ! echo $1 | egrep -q '[^0-9]'
    return $?
}

## returns true if the given uid or username is that of the current user
am_i () {
        [ "$1" = "`id -u`" ] || [ "$1" = "`id -un`" ]
}

## takes a username or uid and finds it in /etc/passwd
## echoes the name and returns true on success
## echoes nothing and returns false on failure 
user_from_uid () {
    if isa_number "$1"
    then
                # look for the corresponding name in /etc/passwd
        local IFS=":"
        while read name x uid the_rest
        do
                if [ "$1" = "$uid" ]
                        then 
                                echo "$name"
                                return 0
                        fi
        done </etc/passwd
    else
        # look for the username in /etc/passwd
        if grep -q "^${1}:" /etc/passwd
        then
                echo "$1"
                return 0
        fi
    fi
    # if nothing was found, return false
        return 1
}

## Parses a string of comma-separated fstab options and finds out the 
## username/uid assigned within them. 
## echoes the found username/uid and returns true if found
## echoes "root" and returns false if none found
uid_from_fs_opts () {
        local uid=`echo $1 | egrep -o 'uid=[^,]+'`
        if [ -z "$uid" ]; then
                # no uid was specified, so default is root
                echo "root"
                return 1
        else
                # delete the "uid=" at the beginning
                uid_length=`expr length $uid - 3`
                uid=`expr substr $uid 5 $uid_length`
                echo $uid
                return 0
        fi
}

# unmount all shares first
sh "/etc/network/if-down.d/umountsshfs"

while read fs mp type opts dump pass extra
do
    # check validity of line
    if [ -z "$pass" -o -n "$extra" -o "`expr substr ${fs}x 1 1`" = "#" ]; 
    then
        # line is invalid or a comment, so skip it
        continue

    # check if the line is a selected line
    elif echo $opts | grep -q "comment=$SELECTED_STRING"; then

        # get the uid of the mount
        mp_uid=`uid_from_fs_opts $opts`

        if am_i "$mp_uid"; then
                        # current user owns the mount, so mount it normally
                        { sh -c "mount $mp" && 
                                echo "$mp mounted as current user (`id -un`)" || 
                                echo "$mp failed to mount as current user (`id -un`)"; 
                        } &
                elif am_i root; then
                        # running as root, so sudo mount as user
                        if isa_number "$mp_uid"; then
                                # sudo wants a "#" sign icon front of a numeric uid
                                mp_uid="#$mp_uid"
                        fi 
                        { sudo -u "$mp_uid" sh -c "mount $mp" && 
                                echo "$mp mounted as $mp_uid" || 
                                echo "$mp failed to mount as $mp_uid"; 
                        } &
                else
                        # otherwise, don't try to mount another user's mount point
                        echo "Not attempting to mount $mp as other user $mp_uid"
:
                        echo "Not attempting to mount $mp as other user $mp_uid"
                fi
    fi
    # if not an sshfs line, do nothing
done </etc/fstab

wait

Si vous disposez d'une connexion wifi ou d'une connexion non fiable, placez ce qui suit dans /etc/network/if-down.d/:

#!/bin/bash
# Not for loopback!
[ "$IFACE" != "lo" ] || exit 0

# comment this for testing
exec 1>/dev/null # squelch output for non-interactive

# umount all sshfs mounts
mounted=`grep 'fuse.sshfs\|sshfs#' /etc/mtab | awk '{ print $2 }'`
[ -n "$mounted" ] && { for mount in $mounted; do umount -l $mount; done; }
jldugger
la source
2
Cela a très bien fonctionné pour moi. Je noterai que j'ai changé les echocommandes qui sortaient en stdout en logger -t mountsshfscommandes à la place pour que la sortie soit envoyée à syslog.
Matthew
3

Upstart est la méthode préférée pour émettre des scripts ou des services de démarrage dans Ubuntu maintenant, bien que l'édition /etc/rc.localfonctionne toujours. Upstart vous permet de contrôler le moment où le service est exécuté, en vous assurant qu'il se produit après l'établissement de votre connexion réseau.

Il est également possible de modifier les liens symboliques dans /etc/rc.Xd directement (remplacez X par le niveau d'exécution que vous utilisez) et ajoutez un nom tel que S99mount pour vous assurer qu'il est exécuté après la configuration du réseau. Cela devra pointer vers un fichier de script qui monte les sshfs que vous demandez.

Dave K
la source
3

_netdev comme option de montage devrait résoudre ce problème, je crois

benjaminc
la source
je sais, ubuntu et centos ne sont pas les mêmes ... mais dans les centos de toute façon, c'est la bonne façon pour que /etc/init.d/netfs gère les montages sshfs. qui sera appelé après la mise en place du réseau.
anonyme-un
1

Juste une pensée, mais si vous l'utilisez comme serveur de fichiers, NFS ou Samba serait peut-être une meilleure solution que ssh.

Brian
la source
0

Voici une autre solution au cas où vous ne disposez pas d'un certificat de votre hôte distant et devez utiliser un identifiant / mot de passe à la place. J'utilise dans cet exemple le même nom d'utilisateur et les mêmes répertoires utilisés par jldugger pour éviter d'ajouter de la confusion.

  1. Créez un fichier contenant votre mot de passe dans votre répertoire personnel et sécurisez-le:

    echo 'YourRemoteUserPassword' > ~jldugger/.credentials
    chmod 600 ~jldugger/.credentials
    
  2. Modifiez votre /etc/rc.localfichier et insérez la commande suivante en bas, mais avant la "sortie 0":

    sshfs -o password_stdin -o nonempty jldugger@storage:/mnt/HD_a2/ /mnt/storage < ~jldugger/.credentials
    
Celso Pires
la source