Tag: GNU-Linux

Mapeo persistente de dispositivos USB en Linux

Actualmente los sistemas operativos son capaces de detectar y montar dispositivos para poder ser usados por el usuario a través del sistema, haciendo que estos dispositivos conectados al sistema sean accedidos de manera transparente.

En Linux cuando conectamos cualquier dispositivo como un dispositivo USB, el sistema lo mapea automáticamente como un terminal en "/dev". El dispositivo aparece con el prefijo "tty" más un identificador del tipo de conexión que implementa a nivel de hardware el dispositivo (USB, ACM, S, ...) y un número que numera los distintos dispositivos del mismo tipo. Para ver los dispositivos que tiene conectados y mapeados en "/dev" ejecuta los siguientes comandos:

cd /dev   # Movernos a /dev
ls   # Listar elementos del directorio

Debido a que el nombre del mapeo de cualquier dispositivo depende de los dispositivos que haya conectados previamente al sistema operativo, puede resultar complicado automatizar procesos que dependen de dispositivos que pueden ser conectados y desconectados en caliente (mientras el sistema operativo está encendido). Para solucionar el problema vamos a realizar un re-mapeo sobre el mapeo automático que hace el sistema.

Lo primero que hay que identificar es el IDVENDOR y IDPROUDCT del dispositivo que queremos mapear de manera persistente. El IDVENDOR es un número que identifica al fabricante del dispositivo y el IDPRODUCT es otro número que identifica al producto del vendedor. Con estos dos valores, suele ser suficiente para mapear unívocamente dispositivos (a no ser que tengamos varios dispositivos idénticos conectados 🙁 , pero eso también tiene solución 😉 ). Para listar los dispositivos y ver ambos valores ejecuta "lsusb":

lsusb
# Result
Bus 001 Device 004: ID 0846:9041 NetGear, Inc. WNA1000M 802.11bgn [Realtek RTL8188CUS]
Bus 001 Device 005: ID 16d0:0856 MCS 
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Detectar cuál es el dispositivo es tan fácil como hacer "lsusb" antes de conectar el dispositivo  y volver a hacer "lsusb" con el dispositivo conectado. El valor del IDVENDOR es el valor comprendido entre el ID y los dos puntos, y el IDPRODUCT el valor comprendido entre los dos puntos y el primer espacio en blanco.

Si necesitamos mapear varios dispositivos de un mismo producto que son de un mismo fabricante, repetiremos el mismo proceso pero listando los puertos conectados y mapedados en "/dev" para conocer el mapeo que le asigna el sistema (ver primer snippet de código) y procederemos a ejecutar el siguiente comando para conocer el el valor SERIAL del dispositivo:

udevadm info -a -n /dev/ttyXXX | grep '{serial}' | head -n1
# Resultado
ATTRS{serial}=="XXXXXXXX"

Donde ttyXXX puede ser ttyUSB0, ttyUSB1, ttyUSB2 ..., ttyACM0, ttyACM1, ttyACM2 ..., ttyS0, ttyS1, ttyS2 ... El valor que nos devuelve de SERIAL es un identificador único para el dispositivo conectado.

Con esta información vamos a crear unas reglas para que al conectar el dispositivo nos realice el mapeo de manera persistente y estática de los dispositivos conectados. Para ello vamos a definir unas reglas UDEV en el siguiente directorio "/etc/udev/rules.d", creando el fichero "99-usb-serial.rules":

sudo nano 99-usb-serial.rules

El fichero lo crearemos con la siguiente estructura si queremos mapear un dispositivo de acuerdo a un un fabricante y producto:

SUBSYSTEM=="tty", ATTRS{idVendor}=="XXXX", ATTRS{idProduct}=="XXXX", SYMLINK+="nombre_mapeo_1"
SUBSYSTEM=="tty", ATTRS{idVendor}=="XXXX", ATTRS{idProduct}=="XXXX", SYMLINK+="nombre_mapeo_2"
...

Si además necesitas diferencia diversos dispositivos de un mismo fabricante, añade el serial del dispositivo:

SUBSYSTEM=="tty", ATTRS{idVendor}=="XXXX", ATTRS{idProduct}=="XXXX", ATTRS{serial}=="XXXXXXXX", SYMLINK+="nombre_mapeo_1"
SUBSYSTEM=="tty", ATTRS{idVendor}=="XXXX", ATTRS{idProduct}=="XXXX", ATTRS{serial}=="XXXXXXXX", SYMLINK+="nombre_mapeo_2"
...

Deberemos completar los valores "XXXX" con la información que hemos recogido en los pasos anteriores y guardamos haciendo CTRL+O y salimos con CTRL+X.

El fichero de reglas que hemos definido crea enlaces simbólicos que apuntan a las direcciones de acceso de los dispositivos y dichos enlaces simbólicos siempre apuntarán al dispositivo que hemos definido.

Si tras generar el fichero de reglas, no se realiza el mapeo que hemos definido, prueba conectar y desconectar el dispositivo, o a reiniciar el sistema. Os aparecerá en "/dev" un enlace simbólico con el nombre que hayáis definido en "SYMLINK+"

A la hora de usar estos mapeos desde scripts de Linux, debeís usar el comando:

readlink -f [symbolic_link]

De esta forma se obtiene la ruta completa a donde apunta el enlace simbólico y podremos programar scripts de manera más transparente, gracias al mapeo, el cual  nos generará un enlace simbólico persistente al dispositivo que conectemos.

 

Eligiendo licencia Open Source

En mi trabajo actual, muy a menudo me encuentro con el dilema de tener que licenciar código. Este aspecto es importante, porque si tu código va a ser liberado públicamente como Software Libre en una plataforma como puede ser GitHub, es necesario que dediques unos minutos a pensar qué licencia poner y qué implicaciones tiene cada licencia. Además es muy recomendable que no subas ningún código sin explicitar el tipo de licencia a la que está sujeto, porque la ausencia de licencia y su publicación de manera pública en la red, implica que quien acceda a ese código "hará lo que quiera con él o por lo menos lo que legalmente pueda en su país".  Por defecto a un código sin licencia se le aplican las leyes en materia de Copyright del país, que además pueden variar en función de cada país. En caso de no incluir licencia, es aconsejable un aviso de Copyright con el año y el nombre del autor.

Mi consejo es que no te la juegues y deja claro lo que se puede hacer o no con tu software, se use por quien se use, en el país que sea.

Si buscas por Internet verás numerosos artículos que hablan sobre los tipos de licencia e incluso presentan categorizaciones de las mismas a fin de ordenarlas para que al lector le resulte más fácil elegir la que realmente necesita. Una posible categorización es la que divide a las licencias en 3 grandes grupos que son Copyleft Fuertes, Copyleft Débiles y Permisivas, tal como se presenta en el Blog de Víctor Goñi, que además nos presenta las cuatro libertades para los usuarios definidas por Richard Stallman y la compatibilidad entre las licencias de los distintos grupos. También tenéis una buena referencia en Hypertextual. Yo por mi parte voy a intentar explicar de manera breve los distintos grupos y algunas de sus licencias más usadas y extendidas, tomando como base la referencia de Hypertextual.

mpl-apache-gpl

 


Copyleft Fuertes

Se denomina a una licencia como Copyleft Fuerte, cuando las obras derivadas de un programa no pueden ser enlazadas por programas que no sean libres. Esto no prohíbe la acción contraria; que un programa con Copyleft fuerte enlace a un programa privativo.

El objetivo del Copyleft fuerte es no dar ventajas a los desarrolladores de software privativo, ya que estos podrían usar los programas creados para indirectamente privar las libertades de los usuarios. De este modo, un programador que desarrolle un programa privativo no podrá usar el código de uno libre para facilitarse el trabajo.

Entre las licencias más comunes tenemos:

  • GNU General Public License (GPL) 3.0: Creada por la Free Software Foundation como parte del proyecto GNU, es una de las más populares y utilizadas en la comunidad. Exige la publicación del código fuente y que todos los trabajos derivados del original conserven la misma licencia GPL, no permite enlaces con módulos privativos (de código cerrado) y requiere que todos los cambios realizados a la versión original sean reflejados en el código fuente con sus respectivos autores. Además posee ventajas únicas respecto a otras licencias como protección contra la tivoización y protección contra las leyes de DRM. Los derechos de autor deben conservarse tanto en el código fuente como en los binarios.
  • GNU General Public License (GPL) 2.0: Es la versión previa a la GPL 3.0, también creada por la Free Software Foundation como parte del proyecto GNU. Tiene características similares a la versión 3.0 pero carece de protección contra la tivoización, protección contra las leyes de DRM y no considera software que se ejecuta a través de la red. La Free Software Foundation desaconseja su uso para proyectos nuevos, en su lugar recomienda la GPL 3.0.

Copyleft débiles

Se denomina a una licencia como Copyleft débil cuando las obras derivadas de un programa pueden ser enlazadas por programas que no sean libres.

El objetivo del Copyleft débil es que cuando haya ya alternativas gratuitas privativas del mismo programa, dejar que programas privativos usen el programa, para así facilitar la adopción de programas libres.

Entre las licencias más comunes tenemos:

  • GNU Lesser General Public License (LGPL) 3.0: Es una licencia con características y beneficios similares a la GPL 3.0, pero con la diferencia que permite enlazar módulos privativos al código, por eso se considera una licencia débil. La Free Software Foundation sólo la recomienda para circunstancias especiales y estrictamente necesarias.
  • Mozilla Public License (MPL) 2.0: Creada por Mozilla Foundation para publicar la mayoría de sus aplicaciones y utilizada por muchos otros programas en la actualidad. Es una licencia que busca un balance entre las licencias permisivas (como la BSD) y las copyleft fuertes (como la GPL). Exige la publicación del código fuente y que cualquier derivado o extensión sea publicado bajo la misma licencia MPL. Sin embargo considera términos en los cuales el código licenciado puede ser parte de una aplicación más grande y esa aplicación puede contener módulos licenciados bajo cualquier otro esquema, incluso privativo. En otras palabras, permite que módulos libres puedan convivir con módulos privativos. No requiere que los cambios realizados sean reflejados en el código fuente y los derechos de autor deben mantenerse tanto en el código fuente como en los binarios.
  • Eclipse Public License (EPL) 1.0: Es una licencia muy similar a la Mozilla Public License ya que busca un equilibrio entre licencias permisivas y fuertes, teniendo como objetivo principal hacerla atractiva para los ambientes de negocios. No requiere ningún seguimiento en los cambios y sólo exige la publicación del código fuente cuando las modificaciones se consideran un trabajo derivado y no una extensión o un módulo separado. Los trabajos derivados deben ser publicados siempre bajo la licencia EPL. Esta licencia es usada por la Eclipse Foundation y nace como reemplazo a la Common Public License.

Licencias Permisivas

Una licencia de software libre permisiva, también conocida como minimalista o liberal, es una licencia de software libre flexible respecto a la distribución, de modo que el software pueda ser redistribuido como software libre o software propietario, siendo libre la licencia original del autor.

La característica peculiar de estas licencias se debe a que no poseen copyleft, ya que el trabajo derivado no tiene por qué mantenerse con el mismo régimen de derechos de autor que el original. Esto maximiza la libertad para quien recibe el software y quiere desarrollar algo derivado, permitiéndole elegir entre el amplio abanico de licencias existentes. No obstante, desde el punto de vista de los usuarios, esto se puede considerar como una restricción a su libertad, en el sentido de que el software propietario siempre restringe las libertades de los usuarios del mismo y las licencias permisivas, abren esta posibilidad.

Entre las licencias más comunes tenemos:

  • Apache 2.0: Es la licencia creada en principio por la Apache Software Foundation para publicar los paquetes del proyecto Apache, sin embargo en la actualidad es usada para muchos otros proyectos. Se considera una licencia permisiva porque no requiere que los trabajos derivados sean publicados bajo la misma licencia y tampoco exige la liberación del código fuente. Los cambios a la versión original deben reflejarse en un archivo en el código fuente y pueden ser publicados usando cualquier otra licencia. Lo más importante de esta licencia es que los derechos de autor deben conservarse tanto en el código fuente como en los binarios.
  • MIT: Es una licencia perfecta si lo que quieres es llegar al mayor número de desarrolladores y no te importa en dónde o cómo puede ser usado tu código. No se considera una licencia para software libre pues no garantiza la libertad de la aplicación, lo único que exige es que los derechos de autor sean incluidos en todas las copias o posibles porciones del software. Recibe su nombre debido a que fue la licencia usada por el Instituto de Tecnología de Massachusetts (MIT en inglés) para publicar la versión original del sistema de ventanas X.
  • BSD 2-Clause: Conocida también como licencia BSD Simplificada o licencia FreeBSD, es otra licencia permisiva o no copyleft que solamente exige que los derechos de autor y las resignaciones de garantía sean incluidas en todas las distribuciones del software, bien sea en forma de código o en binario. Al igual que la licencia MIT, es ideal si no te interesa lo que la gente pueda hacer con el código de tu aplicación y quieres llegar a un mayor número de desarrolladores.

 

He presentado los 3 grupos de licencias Open Source y las licencias más comunes dentro de cada grupo, pero seguramente estés pensando: "Ufffffff, necesito algo más práctico y ágil para de un golpe de vista poder seleccionar mi licencia...".  Por ello os facilito la siguiente referencia, en la que mediante tablas  e muestran los permisos, las condiciones y las limitaciones de cada licencia:

http://choosealicense.com

Espero que este artículo os haya ayudado a comprender las licencias más comunes y a elegir, en consecuencia de manera más rápida, la que necesitéis para vuestro software.

 

Marcando estilo en tu Shell de Linux

En esta entrada os voy a explicar cómo personalizar vuestra Shell de Linux, pero antes de nada me gustaría aclarar ciertos conceptos que suelen confundirse y que son los siguientes:

  • Terminal = tty = Entorno de entrada y salida de texto
  • Console = Terminal físico
  • Shell = Intérprete de línea de comandos

Hablando en tiempos pretéritos, la forma de interactuar con computadoras Unix era mediante dispositivos teleprinter parecidos a máquinas de escribir, algunas veces llamados teletypewriter o "tty".

teletypewriter

El nombre de terminal viene del punto de vista de la electrónica y el nombre consola viene del punto de vista del mueble. En sistemas tipo Unix, tty es el tipo de fichero particular que implementa un número de comandos adicionales (ioctls) más allá de lectura y escritura. Terminal es asumido como un sinónimo de tty y algunas ttys son proveídas por el kernel del sistema operativo a favor de un dispositivo de hardware (como el teclado, modem o puertos seriales). Otras ttys, llamadas también pseudo ttys, son proveídas por programas llamados emuladores de terminal, como son Xterm, Screen, SSH...

Una consola generalmente es un terminal físicamente hablando, que hace referencia al primer terminal conectado a la compuradora. En algunos sistemas como Linux y FreeBSD, la consola dispone de múltiples ttys que pueden ser seleccionados mediante la combinación de teclas:

CTRL+ALT+[F1 ... F12]

Siendo cada uno de los Fx desde F1 a F12 los distintos tty disponibles en el sistema.

Un shell es la interfaz principal que los usuarios ven cuando inician sesión, y cuyo propósito es iniciar otros programas. En sistemas Unix, shell hace alusión a la línea de comandos, cuya finalidad es recibir nombres de aplicaciones y los ficheros sobre los cuales actúa la misma, al presionar la tecla "enter".

Probablemente la shell más popular para Linux sea Bash, basado en la sintaxis de Bourne Shell, con el que se pueden realizar programas usando instrucciones Bash de cierta complejidad, con una estructura muy parecida a otros lenguajes de alto nivel.

Aclarados los conceptos base, vamos a proceder a dar un estilo propio al inicio de sesión de nuestra shell de Linux. La forma más sencilla de hacerlo es personalizando el fichero "/etc/motd" (Message Of The Day). Para ello ejecutamos el siguiente comando:

sudo nano motd

Se nos abrirá o creara el fichero con permisos de usuario. Dentro deberemos poner en texto plano lo que queramos que aparezca, guardar haciendo CTRL+O y salir con CTRL+X. Si andas falto de ideas puedes entrar a este generador de texto ASCII:

http://patorjk.com/software/taag

O a esta galería de imágenes ASCII:

http://www.chris.com/ascii/joan/www.geocities.com/SoHo/7373/index.html

Cuando guardes el fichero, prueba cómo ha quedado abriendo otro terminal y ejecutando el siguiente, le cual abre una sesión ssh de tu usuario contra tu propio equipo:

ssh 127.0.0.1

Pedirá la contraseña de usuario (la introduces) y verás el mensaje. Si no aparece, prueba a salir de la sesión ssh con "exit" y prueba a ejecutar el comando anterior de nuevo. Deberías entonces poder ver tu mensaje.

custom-motd

El MOTD de mi ejemplo podéis encontrarlo en:

https://gist.github.com/RDCH106/876cdb98e7d1b0f3ef22040213a48c40

Si lo que quieres es un mensaje del día más elaborado que no consista en hacer "print" de un texto plano, entramos en "/etc/update-motd.d" y listamos los ficheros con "ls":

update-motd

Se trata de una serie de scripts Bash que poseen una sintaxis especial en el nombre del fichero. Los números que preceden al nombre del fichero, indican el orden en que se ejecutan cuando se inicia una sesión, siendo los números menores los que se ejecutan antes. Estos ficheros a diferencia del "motd" contienen comandos que son ejecutados por el super-usuario "root" y se trata por tanto de ficheros interpretados.

Vamos a crear uno con nombre "20-stats" en el que mostraremos algunas estadísticas del sistema:

sudo nano 20-stats

Y copiamos el siguiente código:

#!/bin/bash

function color (){
  echo "\e[$1m$2\e[0m"
}

function extend (){
  local str="$1"
  let spaces=60-${#1}
  while [ $spaces -gt 0 ]; do
    str="$str "
    let spaces=spaces-1
  done
  echo "$str"
}

function sec2time (){
  local input=$1
  
  if [ $input -lt 60 ]; then
    echo "$input seconds"
  else
    ((days=input/86400))
    ((input=input%86400))
    ((hours=input/3600))
    ((input=input%3600))
    ((mins=input/60))
    
    local daysPlural="s"
    local hoursPlural="s"
    local minsPlural="s"
    
    if [ $days -eq 1 ]; then
      daysPlural=""
    fi
    
    if [ $hours -eq 1 ]; then
      hoursPlural=""
    fi
    
    if [ $mins -eq 1 ]; then
      minsPlural=""
    fi
    
    echo "$days day$daysPlural, $hours hour$hoursPlural, $mins minute$minsPlural"
  fi
}

borderColor=35
headerLeafColor=32
headerRaspberryColor=31
greetingsColor=36
statsLabelColor=33

borderLine="━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
borderTopLine=$(color $borderColor "┏$borderLine┓")
borderBottomLine=$(color $borderColor "┗$borderLine┛")
borderBar=$(color $borderColor "┃")
borderEmptyLine="$borderBar                                                                              $borderBar"

header="$borderTopLine"

uptime="$(sec2time $(cut -d "." -f 1 /proc/uptime))"
uptime="$uptime ($(date -d "@"$(grep btime /proc/stat | cut -d " " -f 2) +"%d-%m-%Y %H:%M:%S"))"

label1="$(extend "$uptime")"
label1="$borderBar  $(color $statsLabelColor "Uptime........:") $label1$borderBar"

label2="$(extend "$(free -m | awk 'NR==2 { printf "Total: %sMB, Used: %sMB, Free: %sMB",$2,$3,$4; }')")"
label2="$borderBar  $(color $statsLabelColor "Memory........:") $label2$borderBar"

label3="$(extend "$(df -h ~ | awk 'NR==2 { printf "Total: %sB, Used: %sB, Free: %sB",$2,$3,$4; }')")"
label3="$borderBar  $(color $statsLabelColor "Home space....:") $label3$borderBar"

stats="$label1\n$label2\n$label3"

# Print motd
echo -e "$header\n$borderEmptyLine\n$stats\n$borderEmptyLine\n$borderBottomLine" 

Guarda haciendo CTRL+O y salir con CTRL+X.

Además vamos a añadir otro script más para personalizar el inicio de sesión del perfil, que lo haremos en "/etc/profile.d" . La razón de hacerlo en profile es debido a que los mensajes MOTD se ejecutan por el root y por ejemplo si hacemos un "whoami" nos devolverá siempre root. Para ello creamos un script "wellcome.sh" que nos saludará y mostrará la fecha y hora:

sudo nano wellcome.sh

Y copiamos el siguiente código:

#!/bin/bash

function color (){
  echo "\e[$1m$2\e[0m"
}

function extend (){
  local str="$1"
  let spaces=60-${#1}
  while [ $spaces -gt 0 ]; do
    str="$str "
    let spaces=spaces-1
  done
  echo "$str"
}

function center (){
  local str="$1"
  let spacesLeft=(78-${#1})/2
  let spacesRight=78-spacesLeft-${#1}
  while [ $spacesLeft -gt 0 ]; do
    str=" $str"
    let spacesLeft=spacesLeft-1
  done
  
  while [ $spacesRight -gt 0 ]; do
    str="$str "
    let spacesRight=spacesRight-1
  done
  
  echo "$str"
}

borderColor=35
headerLeafColor=32
headerRaspberryColor=31
greetingsColor=36
statsLabelColor=33

borderLine="━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
borderTopLine=$(color $borderColor "┏$borderLine┓")
borderBottomLine=$(color $borderColor "┗$borderLine┛")
borderBar=$(color $borderColor "┃")
borderEmptyLine="$borderBar                                                                              $borderBar"

me=$(whoami)

header="$borderTopLine"

# Greetings
greetings="$borderBar$(color $greetingsColor "$(center "Welcome back, $me!")")$borderBar\n"
greetings="$greetings$borderBar$(color $greetingsColor "$(center "$(date +"%A, %d %B %Y, %T")")")$borderBar"

# Print motd
echo -e "$header\n$borderEmptyLine\n$greetings\n$borderEmptyLine\n$borderBottomLine" 

Guarda haciendo CTRL+O y salir con CTRL+X.

Abrimos una sesión ssh de tu usuario contra tu propio equipo, como ya hemos hecho anteriormente, y veremos un inicio de sesión como el siguiente, pero con los datos de tu sesión y equipo.

custom-motd_2

La finalidad de estos MOTD y scripts de perfil, pueden servir para la generación de mensajes informativos concretos para los usuarios, la generación de paneles informativos del sistema para administradores o simplemente para personalizar/corporativizar un sistema Linux.

img_20160414_174706.jpg

Espero que este artículo os haya servido para aprender a explotar estas características tan útiles del inicio de sesión de Linux.

 

¡Maldición! Linux pone mi usuario del sistema al hacer Push con Git

Linux y Git se llevan a las mil maravillas y tal es su integración, que nuestro usuario del sistema operativo es el que se usa por defecto en Git. Además ya tenemos una clave privada y pública generadas para poder trabajar con SSH.

Pero... ¿Qué pasa si mi usuario del repositorio Git con el que tengo que trabajar no es el mismo que el que uso en el sistema?

En Linux, para bien o para mal siempre se rellenará ese usuario automáticamente con el del sistema y nunca te lo preguntará. Únicamente te pedirá la clave, que obviamente no sirve de nada porque el usuario no es el que debiera.

Una forma rápida y sencilla para solucionar este inconveniente, es incluir el usuario dentro de la URL del repositorio.

ssh://user@domain:port/path/repo.git

Suele ser bueno explicitar lo máximo posible la información de conexión dentro de la URL, sobre todo el puerto si no es el de por defecto. En el caso de SSH, el puerto por defecto es 22.

Para modificar la URL del repositorio remoto podemos usar el siguiente comando:

git remote set-url origin [ssh://user@domain:port/path/repo.git]

De esta forma en vez del usuario del sistema, se usará el que especifiquemos por URL y sólo restará meter la clave para poder operar con el repositorio deseado, o si fuera el caso, subiremos la clave pública SSH al servidor del repositorio para poder operar sin usar claves.