SSHFS

From EIK wiki

SSHFS on failisüsteemiklient mis lubab SSH protokollile toetudes haakida kaug-kaustu.

Eeldused

Antud artikkel eeldab, et kasutaja teab mis on SSH ning oskab võtmefaili abil kaugühenduda. Lisaks oleks hea teada mis on haakimine. Kurssi viimiseks saab lugeda artikleid OpenSSH: võtmega autentimine ja Mount.

Vajalik tarkvara

Linux

Linuxi all läheb vaja programmi sshfs. Selle paigaldamine Debianil baseeruvates linuxites:

sudo apt update && sudo apt install sshfs && sudo apt clean

Haakimine

Kui kasutaja on kursis SSH ja haakimisega, siis on üle SSH haakimise süntaks vägagi intuitiivne.

sshfs kasutaja@kuhutahanyhenduda.ee:/kaust/mida/yhendan /haakepunkt/kuhu/yhendan

Lahtihaakimiseks

fusermount -u /haakepunkt/kuhu/yhendatud

Probleemid

Katsetamisel esines selline probleem, et haagitud kaust pani hanguma programmid millega üritasin vaadata kausta, kus haakepunkt asus. Hangusid nii Nemo, kui ka terminal. Viimane küll vaid juhul, kui üritasid tab'i kasutades failinime lõpetada. Muudes kaustades sai vabalt liigelda. Selline olukord tekkis, kui sülearvuti oli olnud mõnda aega uneseisundis, aga tegu võis olla ka muude faktoritega. Kõige tõenäolisemalt on hangumise põhjuseks võrguühenduse katkemine[1]. Kui selline olukord tekkis, tapsin "sshfs" nimelise protsessi ja sain seejärel seadme lahti haakida. Protsesside tapmisest loe lähemalt artiklist Signaalid ja kill. Katsed kinnitavad, et probleemiks on võrguühenduse katkemine.

Haakimine käivitamisel[1]

/etc/fstab ja /etc/fuse.conf

Esiteks tuleb lisada /etc/fstab faili kirje:

sshfs#kasutaja@kuhutahanyhenduda.ee:/kaust/mida/yhendan   /haakepunkt/kuhu/yhendan    fuse    comment=sshfs,noauto,users,exec,uid=1000,gid=1000,allow_other,reconnect,transform_symlinks,BatchMode=yes 0 0

Kokkuvõtvalt kasutame sama süntaksit, mida käsurealt haakimisel ainukese vahega, et prefiks "sshfs#" näitab ära failisüsteemi tüübi.

Parameetrid

comment=sshfs

Lihtsalt kommentaar. Seda läheb hiljem skriptis vaja.

users

Lubab failisüsteemi tavakasutajana haakida. Probleemi korral ei pea alati adminn sekkuma.

uid ja gid

Need kaks parameetrit on vajalikud, sest automaatse haakimise puhul ei käivita haakimisprogrammi mitte kasutaja, vaid süsteem. Kasutades neid parameetreid, anname süsteemile teada kes on kausta omanik. Oma uid ja gid saad teada, trükkides terminali "id". Kasuta enda numbreid, mitte näites antud numbreid.

noauto

Keelab failisüsteemi haakimise operatsioonisüsteemi käivumisel, sest võrguühendus pole sel hetkel veel üleval.

BatchMode=yes

Ütleb sshfs protsessile, et ärgu parooli küsigu, sest automaatse haakimise skript seda sisse trükkima ei hakka. Kasuta võtmetega autentimist. Teiseks lubab see parameeter ssh ühenduse jõudeseisundit. Ilma selleta haagitaks kaust lahti, kui seal mõnda aega liiklust ei toimu.


Järgnevaks ava fail /etc/fuse.conf (loo see fail, kui seda ei eksisteeri) ja lisa sinna järgmine rida:

user_allow_other

/etc/fstab haakimise testimine

mount /haakepunkt/kuhu/yhendan

Ja vaata kas kaustale tekib sisu.

Automaatne haakimine

Normaalse kasutamise saavutamiseks on vajalik, et kaust võrguühenduse kadumisel lahti haagitakse, ja võrguühenduse taastumise korral tagasi külge haagitakse.

Arvutis peaksid olema kaustad nimega /etc/network/if-up.d ja /etc/network/if-down.d. Nende sees olevad skriptid käivitatakse vastavalt kas siis kui arvuti võrku ühendub, või võrguühenduse kaotab. Loo administraatoriõigustes kaks faili:

/etc/network/if-up.d/mountsshfs

#!/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"
		fi
    fi
    # if not an sshfs line, do nothing
done </etc/fstab

wait

/etc/network/if-down.d/umountsshfs

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

Siis anna mõlemale failile käivitusõigused ja sea nende omanikuks root:

sudo chmod 755 /etc/network/if-up.d/mountsshfs /etc/network/if-down.d/umountsshfs
sudo chown root:root /etc/network/if-up.d/mountsshfs /etc/network/if-down.d/umountsshfs

Nüüd peaks kõik ilusasti töötama.

Kokkuvõte

Ehkki esmapilgul tundub SSHFS tööle saamine väga pikk ja keeruline protsess, siis tegelikult oli see üpriski lihtne. Vähemalt senikaua kuni antud automaatse haakimise-lahtihaakimise skriptid töötavad.

Lahendus on elgantne ja kordades mugavam kui pidevalt läbi SFTP ühenduda. Samas selle artikli põhiallikaks olev Ubuntu foorumi postitus väidab, et SSHFS kahjuks suuremahuliste andmete ülekandmiseks, varudamiseks ja muudeks suure koormusega tegevusteks siiski hästi ei sobi, kuna kipub taolistes olukordades ebastabiilseks.

Autorid

Henri Paves, AK21, 2018, v1.0

Viited