Dispositivos USB
Cómo conectarlos y montarlos sin tocar la línea de comandos
Objeto del artículo
El objetivo de este artículo es describir la solución que ahora mismo estoy
utilizando en mi sistema para poder acceder a dispositivos "hotplug" USB sin
tener que tocar la consola para nada, y de una forma totalmente visual
Si es usted un fanático de la consola, del gasto mínimo de recursos
y maldice a KDE y GNOME por ser "pesados", probablemente este artículo no es
para usted.
Antes de nada, he de decir que esta "receta" se apoya en dos infraestructuras
del kernel que deben estar configuradas antes para que esto funcione.
La primera es hotplug, el subsistema encargado de gestionar las conexiones y desconexiones
de aparatos que se enchufan en caliente (a día de hoy me consta sólo el subsistema
USB, PCI Hotplug y red)
El segundo es algo más peliagudo, se trata de udev, introducido en la serie 2.6 del kernel
para sustituír devfs y poder dar una visión dinámica de lo que está
conectado al ordenador.
Si su distribución aún no ha adoptado udev, o no lo hará, puede configurarlo
siguiendo otro artículo
Al asunto
¿Qué vamos a hacer? Simple, le diremos a hotplug que cada vez que algún dispositivo
USB se conecte a nuestro ordenador ejecute un script bash que buscará dispositivos
de almacenamiento conectados al USB y este script se encargará de crear enlaces en el
escritorio de todos los usuarios para hacer notar que ese disco está ahí
(es algo similar a lo que MacOS X hace) y actualizar el /etc/fstab (esto último
es para Gnome, que lo hace de una manera un poco diferente)
Lo primero, debemos considerar que, aunque un dispositivo esté conectado
a nuestro ordenador no puede ser montado como usuario a no ser que esté
listado en /etc/fstab. ¿Es esto un problema? Depende. Digamos que tenemos tres puertos
USB, y nos gustaría que si algún día queremos montar a la vez
tres dispositivos USB, la receta nos funcione sin tocar la consola y sin autentificarse como root.
Para eso, necesitamos meter en fstab soporte para tres discos, teniendo en cuenta que
esos discos a su vez pueden tener particiones. Así pues, digamos que monitorizamos
las 4 primeras particiones de los discos y 3 discos,¡¡¡ eso son 15 entradas en /etc/fstab !!!!
(algunos discos se formatean de manera que se monta el dispositivo /dev/sda, y otras con particiones
de manera que hay que montar la partición /dev/sda1 )
Peero... aún más sorprendente, a partir del kernel 2.6.9 se ha creado
un nuevo nombre para dispositivos de acceso por bloques USB de alta velocidad (ub?) con lo
que a priori, no sabemos si un disco será nombrado como sd? o ub?, con lo que tenemos
que poner las dos y ya tenemos ¡¡¡30 entradas!!!
Pero tranquilos, por suerte, se pueden añadir y quitar entradas de fstab según van llegando
al sistema, eso sí debés copiar vuestro /etc/fstab "normal" a /etc/fstab.base de manera
que añadamos en todo momento sobre este archivo...
Como nota, recomendar mantener un cierto orden con los puntos de montaje, con 30 entradas
uno se puede volver loco... un esquema de cómo lo tengo yo montado:
Ahora viene la parte gráfica. Queremos que no sólo sean capaces
de montarlo, queremos que lo pueda hacer un ceporro sin conocimiento alguno de qué
es una consola. ¿Cómo hacerlo?
Relativamente fácil: para los que no lo sepan, en ~/Desktop se guardan las descripciones
de los "iconos" que KDE (para los usuarios de Gnome, estoy investigando como hacerlo...)
pone, y Gnome también los lee.
KDE tiene un tipo especial de icono que se usa para montar y desmontar dispositivos a través
del escritorio. Gnome examina directamente fstab y muestra un icono de "Mi sistema"... para gustos
colores
Si consiguieramos que cuando un dispositivo se conectara al ordenador se puediera colocar uno
de esos iconos en el escritorio ...... ¿se puede? ¡¡SÍ!!
Debemos dar las gracias en este caso a hotplug.
Cuando el kernel llama a hotplug, y más concretamente cuando se conecta un dispositivo
USB se llama a un script que se llama usb.agent y que suele estar alojado en /etc/hotplug/usb.agent
He escrito el siguiente script para que sea llamado desde este otro script, pongo el script ahora
y lo explicamos paso a paso. Por cierto, cópialo a /usr/local/discos/actualiza (o cualquier otra ruta
que elijas si ajustas el script)
#!/bin/sh
#Ruta especifica donde vamos a meter toda la morralla
#de ficheros que este metodo genera
RUTA="/usr/local/discos"
for PEPELU in 1 2 3
do
sleep 4
#fstab.base sera el fstab "verdadero", el que modificaremos a mano
#para cambios definitivos, y /etc/fstab pasara ser "pseudo-dinamico"
#asi que si usas esto y quieres añadir algo de forma definitiva
#hazlo en fstab.base y no en fstab, porque los cambios se perderan.
cp /etc/fstab.base /etc/fstab
#Comprobamos todos los posibles dispositivos que se pueden
#asociar a discos USB
for DISCO in sda sdb sdc sdd uba ubb ubc ubd
#si teneis algun dispositivo fijo que ocupe alguno
#de los nombres, simplemente quitadlos y en paz
do
#si existe el disco....
if [ -e /udev/$DISCO ]
then
#añadimos una entrada a /etc/fstab
echo "/udev/$DISCO /mnt/$DISCO/ auto \
user,noauto,noexec,uid=0,gid=0,umask=000 0 0" >> "/etc/fstab"
#generar archivo de entradas
cp $RUTA/plantilla $RUTA/$DISCO
echo "Dev=/udev/$DISCO" >> $RUTA/$DISCO
echo "MountPoint=/mnt/$DISCO/" >> $RUTA/$DISCO
echo "Name=$DISCO" >> $RUTA/$DISCO
for USER in $(ls /home/)
do
#linkamos a la carpeta de escritorio un
#descriptor de icono que hemos preparado
#previamente. Y lo hacemos para todos los usuarios
#cuyo home este bajo /home
ln -sf $RUTA/$DISCO /home/$USER/Desktop/
done
#hacemos ahora una comprobacion de las particiones que existen
#en el disco
for i in 1 2 3 4
do
if [ -e /udev/$DISCO$i ]
then
#añadimos entradas tambien para la particion
echo "/udev/$DISCO$i /mnt/$DISCO/$DISCO$i/ auto \
user,noauto,noexec,uid=0,gid=0,umask=000 0 0" >> "/etc/fstab"
#estas lineas generan un descriptor de icono para KDE
#a partir de una plantilla que se muestra mas adelante.
cp $RUTA/plantilla $RUTA/$DISCO$i
echo "Dev=/udev/$DISCO$i" >> $RUTA/$DISCO$i
echo "MountPoint=/mnt/$DISCO/$DISCO$i/" >> $RUTA/$DISCO$i
echo "Name=$DISCO$i" >> $RUTA/$DISCO$i
for USER in $(ls /home/)
do
#y volvemos a copiar el archivo.
ln -sf $RUTA/$DISCO$i /home/$USER/Desktop/
done
fi
done
#Y ahora lo que pasa si no esta el disco
else
for USER in $(ls /home/)
do
#nos cargamos todos los enlaces que haya al disco
rm -f "/home/$USER/Desktop/$DISCO*"
rm -f $RUTA/$DISCO*
done
fi
done
#esto es un ejemplo para dispositivos "conocidos" a los
#que hemos personalizado los nombres a traves de udev.
for DISCO in freecom camara-olympus disquetera
do
if [ -e /udev/$DISCO ]
then
#en mi sistema, udev nombra con el nombre convencional
#del kernel, y crea un enlace simbolico al nombre personalizado
#Con esta regla de sed podemos comprobar cual es el nombre
#verdadero del dispositivo personalizado
EXCEPCION=$(ls /udev/$DISCO -l | sed s/"^.*-> "/""/)
for USER in $(ls /home/)
do
ln -sf $RUTA/$DISCO /home/$USER/Desktop/
#no tiene sentido poner entradas duplicadas, asi que nos cargamos
#las referencias al nombre "verdadero" del dispositivo personalizado
rm -f /home/$USER/Desktop/$EXCEPCION*
done
else
#y si no esta el disco nos cargamos las referencias a el.
for USER in $(ls /home/)
do
rm -f /home/$USER/Desktop/$DISCO
done
fi
done
done
NOTA: en mi sistema, mantengo el directorio /dev tradicional, y un /udev donde opera udev (original,¿verdad?)
de manera que si eres un aventurero que tienes udev gestionando tu /dev, debes cambiar todas las entradas
en el artículo de /udev/ a /dev/
Este es el contenido del archivo que se usa como plantilla para generar los descirptores y que debe ser
copiado a /usr/local/discos/plantilla
[Desktop Entry]
Encoding=UTF-8
Icon=hdd_mount
ReadOnly=false
Type=FSDevice
UnmountIcon=hdd_unmount
Podréis ver que el script se ejecuta tres veces,y que antes de cada
ejecución espera 4 segundos. ¿Por qué? Simple, por cómo funcioa el kernel cuando se conecta el dispositivo:
primero el kernel se da cuenta, notifica a hotplug, hotplug lanza el usb.agent y después
se llama a udev, si no esperáramos nada para comprobar la existencia de los dispositivos de udev
como aún no se le ha notificado, nunca existirín los dispositivos y nunca llegar&iaacute; a funcionar.
Se llama tres veces por si acaso, en alguna circunstancia de carga del sistema, udev tarda más de lo normal
en asignar nombres de dispositivo
Repasemos, que el artículo me está quedando espeso... Tenemos un script molón (¿Se nota
que lo he escrito yo?), al que llamaremos actualiza y que copiaremos en /usr/local/discos/ (o cualquier
otra localización si sabes como editar el script) con propiedad de root y permisos de ejecución.
Tenemos también un archivo de plantilla que debemos copiar a /usr/local/discos/plantilla y ya sólo queda
el punto final, decirle a usb.agent que debe ejecutar el script cuando se añade un dispositivo USB
Para eso debemos editar /etc/hotplug/usb.agent (o el equivalente en tu distro, infórmate y buscar una
secció que tenga una pinta similar a :
.
.
.
.
.
#
# What to do with this USB hotplug event?
#
case $ACTION in
add)
# partial workaround for 2.4 uhci/usb-uhci driver problem: they don't
# queue control requests, so device drivers can confuse each other if
# they happen to issue requests at the same time ... it happens easily
# with slow HID devices and "usbmodules".
# starting with 2.5 (DEVPATH set), all hcds must queue control traffic.
if [ "$DEVPATH" = "" ]; then
sleep $HOTPLUG_USB_WAIT
.
.
.
.
.
Esta orden (case $ACTION ) es una orden de control de flujo que en programación indica
qué hay que hacer según qué casos, su estructura es:
case LOQUEHAYQUEVIGILAR
caso1)
;; <---marca el final de un caso
caso2)
;;
caso3)
;;
*) <--- caso por defecto
Esto funciona de la siguiente manera, el programa llega y lee el case, después llega a LOQUEHAYQUEVIGILAR
y comprueba su valor, y act&uacte;a en consecuencia, un ejemplo
Digamos que tenemos una variable que se llama ORDEN, y tres casos que son comer, beber, dormir
si alguien nos ordenadara "come" e hiciésemos un case, se activaría la lista de tares de
comer, algo como:
case ORDEN
comer)
coger tenedor
pinchar comida
meter en boca
;;<---- Aqui acaba la seccion de comer
beber)
coger vaso
llevarlo a la boca
verter bebida en boca
;;
dormir)
hacer la cama
meterse en cama
cerrar los ojos
;;
NOTA: espero que con esto medio se entienda como funciona esto... tampoco hace falta má
¿Qué a ti que te importa? bueno, porque vas a tener que editar un archivo de estos y
más te vale entender como funciona. Deberás buscar el case $ACTION en usb.agent
y añadir a los casos "add" y "remove" una línea, hazlo al final de cada caso (espero que
con las indicaciones de arriba sepas a qué me refiero)
simplemente añade:
exec /usr/local/discos/actualiza &
NOTA: el & del final es muy importante.
Y si lo has hecho bien.... ¡ya está! la próxima vez que enchufes algún
dispositivo USB se mostrará un icono en tu escritorio KDE y en GNOME aparecerá un
icono que no podréis usar para montar la unidad pero te dirá que está ahí
para montarlo a través de "mi sistema" |