Wie mounte ich sshfs beim Booten?

12

Wenn ich eine NAS-Box als 24/7-Dateiserver verwende, möchte ich sshfs verwenden, um von einem Ubuntu 9.04-Desktop aus eine Verbindung dazu herzustellen. Derzeit habe ich diese Zeile in der fstab des Desktops:

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

Ich kann bestätigen, dass es mit mount funktioniert /mnt/storage. Was ich brauche, ist eine Methode zum Mounten beim Start, aber nachdem die Netzwerkverbindung hergestellt ist.

Jldugger
quelle
Wie haben Sie die Authentifizierung eingerichtet? Werden Sie aufgefordert, ein Kennwort einzugeben, wenn Sie das manuell bereitstellen?
Zoredache
Schlüsselpaarauth. Nicht die sicherste, aber wahrscheinlich ausreichend.
Jldugger

Antworten:

8

Gegenwärtig generiert Upstart in Ubuntu keine Netzwerkereignisse. Stattdessen nennt es traditionelles Sysvinit. Standardmäßig ist NetworkManager installiert und wird ausgeführt. Anstatt Netzwerkereignisse für den Start auszulösen, enthält es einen Run-Parts-Dispatcher (/etc/NetworkManager/dispatcher.d/), der sich einfach auf den Run-Parts-Dispatcher von ifupdown (/etc/network/*.d/) verlässt. Insbesondere interessieren Sie sich für /etc/network/if-up.d/ und /etc/network/if-down.d/

Richten Sie zunächst ein unverschlüsseltes ssh-Schlüsselpaar ein, damit Sie den Punkt ohne Aufforderung bereitstellen können. Schreiben Sie ein Skript, platzieren Sie es in /etc/network/if-up.d/ und machen Sie es ausführbar. Folgendes wurde in UbuntuForums entdeckt und war für mich ausreichend:

#!/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

Wenn Sie eine WLAN- oder eine anderweitig unzuverlässige Verbindung haben, fügen Sie Folgendes in /etc/network/if-down.d/ ein:

#!/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
quelle
2
Das hat bei mir super geklappt. Ich werde bemerken, dass ich die echoBefehle, die ausgegeben wurden, in stdout zu logger -t mountsshfsBefehlen geändert habe, damit die Ausgabe zu syslog geht.
Matthew
3

Upstart ist die bevorzugte Methode zum Ausgeben von Startskripten oder -diensten in Ubuntu, obwohl die Bearbeitung /etc/rc.localnoch funktioniert. Mit Upstart können Sie steuern, wann der Dienst ausgeführt wird, und sicherstellen, dass dies nach dem Herstellen der Netzwerkverbindung geschieht.

Es ist auch möglich, die Symlinks in /etc/rc.Xd direkt zu bearbeiten (ersetzen Sie die verwendete Ausführungsebene durch X) und einen Namen wie S99mount hinzuzufügen, um sicherzustellen, dass sie nach dem Netzwerk-Setup ausgeführt werden. Dies muss auf eine Skriptdatei verweisen, die die angeforderten sshfs bereitstellt.

Dave K
quelle
3

_netdev als mount option sollte dies meines erachtens lösen

benjaminc
quelle
Ich weiß, Ubuntu und Centos sind nicht dasselbe ... aber in Centos ist dies die richtige Art und Weise, wie /etc/init.d/netfs Sshfs-Mounts handhabt. Das wird aufgerufen, nachdem das Netzwerk aufgerufen wurde.
anonym-ein
1

Nur ein Gedanke, aber wenn Sie dies als Dateiserver verwenden, wäre NFS oder Samba vielleicht eine bessere Lösung als ssh.

Brian
quelle
0

Hier ist eine andere Lösung für den Fall, dass Sie kein Zertifikat von Ihrem Remote-Host haben und stattdessen ein Login / Passwort verwenden müssen. Ich verwende in diesem Beispiel denselben Benutzernamen und dieselben Verzeichnisse wie jldugger, um Verwirrung zu vermeiden.

  1. Erstellen Sie eine Datei mit Ihrem Passwort in Ihrem Home-Verzeichnis und sichern Sie diese:

    echo 'YourRemoteUserPassword' > ~jldugger/.credentials
    chmod 600 ~jldugger/.credentials
    
  2. Bearbeiten Sie Ihre /etc/rc.localDatei und fügen Sie den folgenden Befehl am unteren Rand ein, jedoch vor dem "exit 0":

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