USB automount

Kamikaze

Warrior of Sunlight
Teammitglied
Ich habe mir in den letzten zwei Tagen ein Skript zusammengeschustert, dass dynamisch eine amd.map, Mountpoints und Links aus /media anhand der Labels erzeugt. Das Skript wird aus der devd.conf aufgerufen, so dass das ganze automatisch aktualisiert wird.

Ich muss jetzt noch etwas aufräumen und dafür sorgen, dass man bestimmte Dateisystemtypen Parameter übergeben kann. Zum Beispiel -o -L=en_GB.UTF-8 für msdosfs oder -o ro für ntfs.
Außerdem muss noch ein Feature eingebaut werden mit dem man Dateisystemtypen mit Anderen (z.B. ntfs mit ntfs-3g) mounten kann.

Wenn hier Interesse besteht werde ich daraus einen Port basteln.
 
Hier ist mal der aktuelle Stand:

/root/bin/automounter
Code:
#!/bin/sh -f

# AMD parameters
a=/var/run/automounter.amd
c=2
w=1
l=/var/run/automounter.amd.log
directory=/var/run/automounter.amd.mnt
map=/var/run/automounter.amd.map

# Timeout in seconds for aquiring the lock.
timeout=30

# A file to remember for which partitions automounter has been configured.
nodes=/var/run/automounter.nodes

# A temporary file for the partitions of the last run.
oldnodes=/var/run/automounter.nodes.old

# The pid of amd.
pidfile=/var/run/automounter.amd.pid

# This is where the links will be created to access the file systems.
linkdir=/media

# This is where the folders to mount the file systems into will be created.
mountdir=/var/run/automounter.mnt

# Lock file.
lock=/var/run/automounter.lock

# Mount isos as cd9660.
iso9660=cd9660

# Config file.
config=/usr/local/etc/automounter.conf
if [ -e "$config" -a ! -d "$config" ]; then
	. "$config"
fi

IFS='
'

update() {
	local pid devices device partitions partition type
	/bin/date

	/bin/cp /etc/amd.map "$map"

	/bin/mkdir -p "$a" "$directory"
	/usr/bin/touch "$nodes"
	/bin/mv "$nodes" "$oldnodes"
	/usr/bin/touch "$nodes"

	/bin/sleep 1

	devices="$(
		/sbin/camcontrol devlist | \
		 	/usr/bin/sed -E 's/<([^>]+)>.*\(([^,]+),.*/\1;\2/1'
		/sbin/atacontrol list | /usr/bin/grep -E '(Master|Slave):' | \
			/usr/bin/grep -v 'no device present' | \
			/usr/bin/sed -E 's/(Master|Slave):[[:space:]]+([^[:space:]]+)[[:space:]]+<(.+)>.*/\3;\2/1'
	)"

	for device in $devices; {
		name="${device%;*}"
		device="${device#*;}"

		partitions="$(
			/sbin/glabel list | /usr/bin/grep Name: | \
			/usr/bin/grep -B1 "Name: $device.*" | \
			/usr/bin/grep -v "Name: $device.*" | \
			/usr/bin/sed 's/.* //1'
		)"

		# Add new mounts.
		for partition in $partitions; {
			type="${partition%%/*}"
			mount="$type"
			options="rw,noatime"

			# Skip on unknown types.
			test "$type" = "label" && continue

			# Remember node.
			echo "$partition" >> "$nodes"

			# Check for config file settings.
			if [ -n "$(eval "echo \"\$$type\"")" ]; then
				mount="$(eval "echo \"\$$type\"")"
			fi
			if [ -n "$(eval "echo \"\$${type}_options\"")" ]; then
				options="$(eval "echo \"\$${type}_options\"")"
			fi

			echo "
$type type:=auto;fs:=\${map};pref:=\${key}/

$partition type:=program;fs:=$mountdir/$partition;mount:=\"/sbin/mount mount -t $mount -o $options /dev/$partition $mountdir/$partition\";unmount:=\"/sbin/umount umount $mountdir/$partition\"
" >> "$map"

			# Skip if already present.
			/usr/bin/grep -E "^$partition\$" \
				"$oldnodes" > /dev/null && continue

			echo "add: $device: $partition: $name"
			/bin/mkdir -p "$mountdir/$partition"
			/bin/mkdir -p "$linkdir/$type"
			/bin/ln -s "$directory/$partition" "$linkdir/$partition"
		}
	}

	# Clean up stale mounts.
	for partition in $(/bin/cat "$oldnodes"); {
		/usr/bin/grep -E "^$partition\$" \
			"$nodes" > /dev/null && continue

		type="${partition%%/*}"

		echo "del: $partition"
		/bin/rm "$linkdir/$partition"
		/bin/rmdir "$linkdir/$type" 2> /dev/null
		/bin/rmdir "$mountdir/$partition"
		/bin/rmdir "$mountdir/$type" 2> /dev/null
	}

	/bin/rm "$oldnodes"

	# Finally restart amd.
	pid="$(/bin/cat "$pidfile" 2> /dev/null)"
	if [ -z "$pid" ]; then
		/usr/sbin/amd -r -p -a "$a" -c "$c" -w "$w" -l "$l" \
			"$directory" "$map" > "$pidfile" &
	else
		/bin/kill -HUP "$pid"
	fi

	/bin/sleep 1

	return 0
}

alias start=update

stop() {
	local pid type

	/bin/date

	pid="$(/bin/cat "$pidfile" 2> /dev/null)"
	if [ -n "$pid" ]; then
		/bin/kill "$pid"
		wait "$pid" 2> /dev/null
	fi
	
	# Clean up stale mounts.
	for partition in $(/bin/cat "$nodes" 2> /dev/null); {
		type="${partition%%/*}"
		echo "del: $partition"
		/sbin/umount -f "$mountdir/$partition" > /dev/null 2>&1
		/bin/rm "$linkdir/$partition"
		/bin/rmdir "$linkdir/$type" 2> /dev/null
		/bin/rmdir "$mountdir/$partition"
		/bin/rmdir "$mountdir/$type" 2> /dev/null
	}

	# Clean up temporary folders.
	/bin/rmdir "$a" "$directory" "$mountdir" 2> /dev/null
	/bin/rm "$pidfile" "$map" "$nodes" 2> /dev/null

	return 0
}

if [ "$1" != "locked" ]; then
	/usr/bin/lockf $lock $0 locked $1 || \
		echo "Lock could not be aquired."
else
	case "$2" in
		start | update | stop)
			eval "$2"
		;;
	esac
fi

/etc/devd.conf
Code:
attach 100 {
	device-name "umass[0-9]+";
	action "/root/bin/automounter update >> /var/run/automounter.log 2>&1";
};

detach 100 {
	device-name "umass[0-9]+";
	action "/root/bin/automounter update >> /var/run/automounter.log 2>&1";
};

/usr/local/etc/automounter.conf
Code:
# ntfs settings
ntfs=ntfs-3g
ntfs_options=rw,noatime,gid=5,umask=113,dmask=002,locale=en_GB.UTF-8

# msdosfs settings
msdosfs_options=ro,-L=en_GB.UTF-8
 
Weil nicht jeder HAL benutzt und der amd schliesslich im base vorhanden ist? AFAIK ist es auch ziemliche Frickelei HAL ntfs3g beizubringen.
Irgendwie ist mir HAL in Sachen Systemsicherheit auch immer suspekt gewesen - wahrscheinlich einfach deswegen, weil ich keine Ahnung davon habe, es aber als Gefahr sehe, solche Arbeiten direkt dem Benutzer zu überlassen. Für Leute mit Komfortabilitätsbewusstsein und Gnome/KDE ist es aber wahrescheinlich einfach nett ;)
 
Ich weiß nicht so recht wie ich das mit HAL anstellen sollte. Vor allem ohne Unterstützung vom Window-Manager.

Meine Lösung ist eben schlanker und hat keinerlei Abhängigkeiten außerhalb des Basissystems.
 
Mhm, stimmt. Ausßerhalb von KDE/Gnome is Ebbe.

Kleine Anmerkung: Das unmounten eines nicht mehr eingesteckten USB Sticks führt doch mit absoluter Sicherheit zu einem Panic, oder? Wenn das immer noch so ist, dann ist diese Vorgehensweise brandgefährlich. Daran sind daher bisher alle devd.conf Lösungen mehr oder weniger gescheitert.
 
Umount -f wird eh erst beim System Shutdown aufgerufen. Das ist wichtig damit am Schluss ordentlich aufgeräumt werden kann. Wenn der Stick nicht gezogen ist fliegen halt bloß alle Anwendungen raus, die immer noch auf dem Mount rumknabbern.

Nach meinen Versuchen ist die Panic nicht mehr zu vermeiden, wenn man einen gemounteten Stick zieht, egal ob umount -f kommt oder nicht. Ich muss noch eine Beispielkonfiguration basteln und die Manual Pages schreiben. Dann werde ich hier ein Paket für den öffenlichen Test reinstellen.

Ich rate übrigens davon ab obiges zu verwenden. Da sind noch diverse Kinderkrankheiten drin.
 
Zuletzt bearbeitet:
Das mit der Panik ist echt ein Problem. Vor ewigen Zeiten hab ich auch mal mit dem AMD rumgemacht und kann nur empfehlen einen sehr kleinen Timout zu nutzen, damit Sticks, die länger als z.B. 5 Sek. nicht genutzt werden nicht mehr gemountet sind.
Das reduziert die Panikrate beträchtlich :)
 
Ich verwende -c 2 -w 1. Das ist schon ziemlich aggressiv. Aber das ganze ist ein Komfortfeature. Kein Ersatz für das nachsehen mit mount ob man das Ding wirklich rausziehen darf.
 
Ich hab nur letztens auf ner ML gelesen, dass es gefixt wurde. Hat aber glaub ich nicht mit dem Stack zu tun, sondern war (nur) ein Patch.
 
Es hat nichts mit dem Stack zu tun. Eigentlich ist der Patch ein dreckiger Würg-Around, der durch jahrelanges Nörgeln als nötig angesehen wurde. Normalerweise würde das VFS panic() aufrufen, wenn es versucht im Speicher gehaltene vnodes auszuschreiben und dabei feststellen muss, dass es auf das zugehörige Medium nicht mehr zugreifen kann. Eigentlich ein logischer Vorgang, da das System per Definition panicen soll, wenn es in einen undefinierten Zustand gerät.
Seit dem der Patch eingepflegt wurde, wird panic() nicht mehr aufgerufen. Stattdessen wird ein Error an den Aufrufenden zurückgegeben und alle vnode die mit dem nicht mehr erreichbaren Gerät verbunden sind im Klo runtergespült. Dies kann zu Datenverlust bis hin zu zerstörten Dateisystemen führen, exakt genauso wie im Falle einer Panic. Nur das das System halt weiterläuft.
Man sollte aber beachten, dass dies Vorgehen die Panic nur in 98% der möglichen Fälle verhindern kann. Es kann zu Punkten kommen, an denen nicht mehr klar zu sagen ist, welche vnodes wir nun freigeben sollen. In diesem Fall haben wir eine wirkliche Inkonsistenz im Kernel, die in jedem Fall zur Panic führen muss.
 
Der 1.0-Release wartet inzwischen auf den Commit.

Eigentlich wollte ich das erst ankündigen, wenn es in den Ports ist, aber ich habe auf unbestimmte Zeit keinen Internetzugang mehr.

Also einfach installieren, und die automounter und automounter.conf Manual pages lesen.
 
Seit dem der Patch eingepflegt wurde, wird panic() nicht mehr aufgerufen. Stattdessen wird ein Error an den Aufrufenden zurückgegeben und alle vnode die mit dem nicht mehr erreichbaren Gerät verbunden sind im Klo runtergespült. Dies kann zu Datenverlust bis hin zu zerstörten Dateisystemen führen, exakt genauso wie im Falle einer Panic. Nur das das System halt weiterläuft.

Absolut richtig, und daher werden Wechseldatenträger gefälligst OHNE Schreibcache gemountet! So ist es auch unter Windoof und ein Panik daher völlig nutzlos aber ärgerlich. Ich bin froh über diesen Patch.
 
Zuletzt bearbeitet:
Ich habe das mal versucht, aber mit sync mounten drückt die Performance wirklich unerträglich.

Ich muss nun nach 2 Wochen feststellen, dass weder meine Updates der BSDadminscripts noch der Automounter committet wurde.

Ich starte jetzt einen neuen Versuch mit dem Automounter. Inzwischen ist der bei Version 1.2 und kann automatisch verschlüsselte Images oder Devices mounten, wenn ein Schlüssel auf einem USB-Laufwerk liegt. Das ganze habe ich mir für die Arbeit gebastelt. Ich habe alle Daten die mit meiner Arbeit bei Porsche zu tun haben auf einem verschlüsselten Image. Der Schlüssel liegt auf einem USB-Stick, den ich immer bei mir trage. Das ist meine Interpretation der Klausel "verantwortungsvoller Umgang mit Daten", die ich unterschrieben habe.
 
Automounter in den FreeBSD Ports

Der Automounter ist nun endlich in der Version 1.3 als sysutils/automounter in den Ports vorhanden. Jetzt benötige ich Feedback, ob die Manual Pages die Einrichtung vollständig und verständlich erklären und natürlich ob alles wie erwartet funktioniert.
 
Hm, bin wohl zu dumm dazu...
Code:
lars@ttyp3 > automounter list
label: <ntfs/Windows>
label: <msdosfs/LG>

<FreeBSD 8.0-CURRENT> [maggie:/media/msdosfs]                             
lars@ttyp3 > ls -l
total 0
lrwxr-xr-x  1 root  wheel  69 May 13 19:15 LG@ -> /var/run/automounter.amd.mnt/msdosfs/4b6ce7a936468f9fec1336d0d1210cb3

lars@ttyp3 > cd LG
LG: No such file or directory.

lars@ttyp3 # mount
/dev/ad0s2a on / (ufs, local, noatime, soft-updates)
devfs on /dev (devfs, local)
/dev/ad0s2d on /var (ufs, local, noatime, soft-updates)
/dev/ad0s2e on /tmp (ufs, local, noatime, soft-updates)
/dev/ad0s2f on /usr (ufs, local, noatime, soft-updates)
linprocfs on /usr/compat/linux/proc (linprocfs, local)
linsysfs on /usr/compat/linux/sys (linsysfs, local)
 
Zurück
Oben