"Después del juego es antes del juego"
Sepp Herberger

miércoles, 28 de octubre de 2015

Clonar pantalla y cañón de vídeo en el inicio de sesión.

Las tarjetas VGA son bastante rebeldes, cuando tienen dos salidas (típicamente una VGA D-sub 15 y una HDMI) a las que conectamos un monitor y un cañón de vídeo el comportamiento es bastante errático en función de la tarjeta de vídeo y los drivers usados: unas veces aparecen clonadas, otras veces como escritorio extendido y, por último, algunas veces aparece apagada una de ellas.

Como normalmente nuestra intención es que ambas aparezcan clonadas (ya que es lo que desea el usuario el 99% de las veces) lo mejor es poner un script que nos las clone usando el comando "xrandr". Luego, el propio usuario puede cambiar esa configuración por si mismo usando el programa "arandr".

En mi caso tengo un PC con 2 salidas de vídeo: VGA-0 (que va al monitor) y DVI-I-0 (que va al cañón de vídeo). El nombre de cada salida se conoce ejecutando "xrandr" sin parámetros, tal como conté aquí.

El comando que debemos ejecutar es:
xrandr --output VGA-0 --rate 60 --mode 1024x768 --output DVI-I-0 --mode 1024x768 --same-as VGA-0
En el que se fuerza una resolución de 1024x768 en ambas pantallas y hago que DVI-I-0 se clone de VGA-0. El monitor es realmente de 16:9, mientras que el cañón es de 4:3, por lo que la resolución de 1024x768 en el monitor queda un poco deforme, pero si queremos tener lo mismo es lo que hay. Se podría jugar con los parámetros "panning" y "scale" de xrandr para intentar conciliar 2 resoluciones distintas en el clonado, pero al final queda como el discurso de C's: totalmente amorfo por querer mezclar 2 agua y aceite, así que no he seguido por ese camino.

Para que esto se ejecute automáticamente en el arranque del sistema hay que poner el comando en algún script de inicio. En mi caso, como uso gdm3 para iniciar sesión lo añado al final de "/etc/gdm3/PreSession/Default", que es un script que se ejecuta justo antes de que el usuario inicie sesión en la máquina. De esta manera garantizo que cada vez que se haga login se configuren ambas pantallas como clonadas, independientemente de que alguien lo haya cambiado durante la sesión anterior.

martes, 27 de octubre de 2015

Desactivar el audio HDMI y dejar solo el sonido analógico mediante una tarea puppet.

En algunos de nuestros PC el sistema identifica 2 tarjetas de sonido: la tarjeta analógica tradicional y otra salida digital vinculada a la salida HDMI de la tarjeta VGA. Tenemos los altavoces conectados a la salida analógica, de tal manera que si por cualquier motivo en pulseaudio se selecciona (y pasa, no sabemos como, pero pasa) de forma espontánea la salida digital, el sonido deja de salir por los altavoces normales, que quedan mudos ante el desconcierto de los usuarios.

Lo solucionaremos en dos partes: primero veremos como hacer desaparecer la tarjeta de sonido digital y luego como automatizarlo vía puppet.

1. Desactivar la tarjeta de sonido.

En Debian Squeeze esto se evitaba blacklistando el módulo del kernel que maneja la tarjeta digital de audio (snd_hda_codec_hdmi), pero en Wheezy este método no funcionaba así como así. Menos mal que nuestro compañero Ricardo encontró la solución con el siguiente comando:
# echo 1 > "/sys/bus/pci/devices/..../remove"
Este comando enviado al dispositivo pci en concreto que representa nuestra tarjeta digital de audio hace que se vaporice, desapareciendo del hardware de la máquina, de pulseaudio y de todos lados. La tarjeta analógica queda como única salida de audio.

Antes hay que saber exactamente cual es el dispositivo pci asociado a la tarjeta de audio:
bus=$(lspci | grep "RV620 HDMI Audio" | cut -d" " -f1)
if [ -n $bus ]
then
      echo 1 > "/sys/bus/pci/devices/0000:00:01.0/0000:$bus/remove"
fi
Siendo "RV620 HDMI Audio" la cadena que identifica nuestra tarjeta de audio HDMI (la descripción se saca con la orden lspci) y debería adaptarse la tarjeta que tenga cada cual. Escrito de forma mas breve sería:
bus=$(lspci | grep "RV620 HDMI Audio" | cut -d" " -f1); test -n $bus && echo 1 > "/sys/bus/pci/devices/0000:00:01.0/0000:$bus/remove"
Como debe ejecutarse al arrancar el sistema, para que quede desactivado desde el principio, el sitio mas adecuado es en /etc/rc.local, antes del exit 0 con el que acaba dicho script.

2. Insertar una línea en rc.local de forma automatizada vía puppet.

Si queremos meter esta línea en rc.local vía puppet (para así poder aplicarlo de forma automatizada en un grupo de máquinas) tenemos que encontrar la manera de añadir dicha línea en el fichero antes del exit 0, verificando que no estuviera ya. Hay varias maneras de hacerlo, pero me he decantado por usar un define de puppet.

Actualmente tengo en /etc/puppet/defines/* de mi servidor puppet un conjunto de funciones puppet útiles para tratar con ficheros y lineas de texto. Es una gran idea cogida de mi compañero Esteban Navas y son una serie de funciones descritas en https://projects.puppetlabs.com/projects/puppet/wiki/Simple_Text_Patterns/1:

  • delete_lines.pp
  • line.pp
  • prepend_if_no_such_line.pp
  • replace.pp

Aunque ninguna servía para hacer lo que quiero (añadir una línea que no está antes del "exit 0" del rc.local), los defines anteriores me sirven de base para hacerlo. El nuevo define en cuestión queda:
# cat /etc/puppet/defines/add_line_above.pp

#Añade la linea "line" al fichero "file", siempre que la cadena "search" no esté en el fichero.
#La línea la añade inmediatamente por encima de la línea que contenga la cadena "above".
#Usado por ejemplo para añadir lineas a /etc/rc.local por encima del "exit 0" con el cual
#siempre finaliza dicho script.

define add_line_above($file, $line, $search, $above) {
    exec { "/bin/sed -i '/${above}/i\\${line}' '${file}' ":
           unless => "/bin/grep -q '${search}' '${file}'"
    }
}
A continuación tenemos que referenciar este define metiéndolo en el init.pp de una tarea puppet específica que hagamos o bien añadiéndolo a una ya hecha (yo prefiero eso: hacer tareas omnibús que aplican conjuntos de pequeños ajustes de configuración antes que llenar todo de pequeñas tareitas haiku muy especializadas)

Sea como fuere, en el init.pp que escojamos tenemos que importar los .pp de /etc/puppet/defines, poniendo al principio del fichero, antes del "class":
import "/etc/puppet/defines/*.pp"
Y luego dentro del "class":
add_line_above { desactiva_audio_hdmi:
              file=> "/etc/rc.local",
              line=> 'bus=$(lspci | grep "RV620 HDMI Audio" | cut -d" " -f1); test -n $bus && echo 1 > "/sys/bus/pci/devices/0000:00:01.0/0000:$bus/remove"',
              search=> "RV620",
              above=> "^exit 0$"
}

Y ya está. Eso lo que hará será modificar el fichero rc.local de todos los equipos que usen la clase puppet para añadir:
bus=$(lspci | grep "RV620 HDMI Audio" | cut -d" " -f1); test -n $bus && echo 1 > "/sys/bus/pci/devices/0000:00:01.0/0000:$bus/remove"
Justo antes del exit 0 con el que finaliza dicho fichero. Y con esto ya tenemos ambos objetivos conseguidos, trabajo hecho :-).


miércoles, 21 de octubre de 2015

Como cambiar la contraseña de root de un Linux cuando no la sabemos previamente.

A veces heredamos o nos llega un sistema Linux en el que la contraseña de root es desconocida. Puesto que las contraseñas de Linux son en principio cuasi-imposibles de descifrar, no nos queda otra que cambiar la contraseña de root por una que conozcamos, ¿cómo se hace esto?.

Primero debemos arrancar con un CD o Pendrive conteniendo un Linux. Puede ser un SystemRescueCD, un Clonezilla o cualquier disco de instalación Live (uno de Ubuntu o Mint, por ejemplo). Una vez hemos arrancado tendremos que abrir un terminal. En un SystemRescueCD el terminal está allí mismo, en un Clonezilla hay que seleccionar la opción "Enter shell..." enlos menús y sobre un Linux Live habría que ir al menú de inicio y ejecutar la aplicación de terminal desde allí.

Ahora pasamos a ejecutar los siguientes comandos (el "sudo su" puede que no sea necesario, dependiendo de que distribución estemos usando):
$ sudo su
# fdisk -l

Esto nos mostrará las particiones del disco duro del PC, algo así como:
Disco /dev/sda: 160.0 GB, 160040803840 bytes
.....
.....
Dispositivo Inicio    Comienzo      Fin      Bloques  Id  Sistema
/dev/sda1   *        2048   156250111    78124032   83  Linux
/dev/sda2       156264255   312576704    78156225   83  Linux
En esta lista de particiones estará la que contiene el sistema Linux al cual queremos cambiar la contraseña. En el ejemplo anterior sería /dev/sda1 (es una partición de Linux y está marcada como arrancable).

Una vez identificada la partición, la montamos:
# mount /dev/sda1 /mnt
Y entramos en ella con una jaula chroot:
# chroot /mnt
Puede que nos de algún error relacionado con "zsh" u otra shell, en ese caso lo haremos así:
# chroot /mnt /bin/bash
Con esta orden chroot estamos dentro del Linux contenido en el disco duro, ya que nuestro / ha pasado a ser /dev/sda1. Eso quiere decir que cualquier comando que tecleemos se hará y tendrá efecto sobre dicho Linux y no sobre el sistema con el que hemos arrancado. Por tanto, haciendo:
# passwd root
Nos pedirá la nueva contraseña de root: la introducimos por duplicado y ya está, esa será la contraseña de root del sistema instalado en el disco duro. Salimos de la jaula y desmontamos:
# exit
# umount /mnt
Si por algún motivo el comando "passwd root" no funciona podemos optar por lo siguiente una vez averiguada la partición donde está nuestro Linux:
# mount /dev/sda1 /mnt
# nano /mnt/etc/shadow
# # Borrar contraseña root
# umount /mnt
Si no funciona el editor "nano" probaremos con "vi". Por "borrar contraseña de root" quiero decir localizar en /etc/shadow la línea parecida a:
root:$6$0UeP/qy$XzJ3Ztmd0wsNrNx1rEnnp8K2VYtHsEO1so5UN7FsfaDPEXTxImxYyKAWpeIvQrQwxNwTNjUD25gz6aVq5/:16280:0:99999:7:::
y borrar todo lo que hay entre el primer y segundo ":", quedando:
root::16280:0:99999:7:::
Con esto quedamos la contraseña de root en blanco, pudiendo entrar con facilidad.

Una vez hecho esto reiniciamos el sistema, quitando el pendrive o el CD y arrancando con el sistema en el disco. Ahora podremos entrar como root con la contraseña que hemos establecido. Como vemos, es mucho mas fácil de lo que parecía.

¿Y tú de quién eres?

Más de una vez he necesitado saber la procedencia de un fichero que encontramos dentro de nuestro sistema Debian y no se de dónde ha salido. Los pasos que sigo son:

1) Averiguar a que paquete pertenece el fichero.

Eso lo hago con:
# dpkg -S /usr/lib/x86_64-linux-gnu/libavformat.so.54
libavformat54:amd64: /usr/lib/x86_64-linux-gnu/libavformat.so.54
Como vemos, el fichero en cuestión vino con el paquete libavformat54:amd64.

Si nos dice:
dpkg-query: no se ha encontrado ningún paquete que corresponda con el patrón ....
entonces el fichero no ha venido dentro de un paquete del sistema y va a ser bastante mas complicado saber su procedencia.

2) Averiguar de dónde proviene el paquete.

Los paquetes de nuestro sistema pueden venir de distintos repositorios o haber sido instalados a mano, ¿cómo sabemos su origen?, pues con:
# apt-cache policy libavformat54:amd64
libavformat54:
 Instalados: 8:1.0.10-dmo1
 Candidato:  8:1.0.10-dmo1
 Tabla de versión:
     *** 8:1.0.10-dmo1 0
              500 http://ldap/mirrors/multimedia-wheezy/ wheezy/main amd64 Packages
              100 /var/lib/dpkg/status
Segun se ve, viene de multimedia-wheezy. En mi caso de un mirror local que hago cada noche en mi servidor "ldap". De no tener mirror su origen seria el repositorio oficial de Debian Multimedia: http://www.deb-multimedia.org/dists/oldstable/main/.

Si el paquete ha sido instalado a mano habría que busca el origen del .deb por Internet. A las malas, podemos usar dpkg-repack para "reconstruir" el paquete .deb desde el sistema donde está instalado, de tal forma que tenemos el .deb tal y como lo descargamos originalmente, con la ventaja de que podremos guardar una copia del mismo y reinstalarla cuando y donde queramos.

Bueno, pues con esto ya se de donde vino el fichero y puedo instalar el paquete que lo trajo cuando me haga falta tener el mismo fichero en otra máquina.

3) ¿Y si el fichero no está en nuestro sistema, pero queremos saber en que paquete de los repositorios está?.

Si queremos buscar un fichero en paquetes no instalados en el sistema usamos apt-file:
# apt-get install apt-file
# apt-file update
# apt-file find kwallet.h
kdelibs5-dev: /usr/include/kwallet.h
libkf5wallet-dev: /usr/include/KF5/KWallet/kwallet.h
Ojo: esto sólo buscará el fichero en los repositorios que tenemos configurados en el sources.list y sources.list.d de nuestra máquina, no mas allá.

Bueno, pues con estos consejos podremos localizar el origen de los ficheros que rulan por nuestro sistema, de igual manera que se puede hacer con la herramienta equivalente de Windows....



Y así es como tenemos identificado cualquier fichero que ande por nuestros discos duros.

martes, 13 de octubre de 2015

SimpleScreenRecorder para Debian Wheezy

Un compañero profesor me pidió buscar un software sencillo para grabar las clases capturando toda la actividad en pantalla al usar la pizarra digital en un vídeo que luego podría editar para publicarlo o revisarlo.

Estuve buscando y encontré como opción mas sencilla y completa el SimpleScreenRecorder, que incluso permite grabar el sonido. Yo lo probé en mi Linux Mint y funcionaba estupendamente. El problema vino cuando se dió cuenta de que había que hacerlo funcionar en Debian Wheezy de 64bits, que es el sistema que tenemos en las aulas.

La primera opción fue buscar versiones antiguas para Ubuntu o Mepis, pero los paquetes encontrados daban errores con las versiones de los paquetes dependientes al instalarlos en nuestro Debian Wheezy.

Podría haber intentado probar versiones de otras distribuciones Linux, convirtiéndolas con alien, pero había otra opción más divertida: compilar desde los fuentes. Los afectados de fetichindows (neopalabro formado por la fusión de conceptos "fetichismo" y "Windows") que odian-temen Linux  dicen que los linuxeros estamos todo el día compilando programas desde que amanece hasta que se pone el sol. Pues vamos a darles la razón por 10 minutos.

Tenemos este manual  para compilarlo para Debian Jessie, así que no debe ser muy distinto hacerlo para Wheezy. Vamos allá, haremos todo con un usuario regular que tenga acceso sudoer (luego podemos quitar dicho acceso). Los pasos son:

$ cd
$ wget https://github.com/MaartenBaert/ssr/archive/master.tar.gz
$ tar xfvz master.tar.gz
$ sudo dpkg --add-architecture i386
$ sudo apt-get update 
$ sudo apt-get install build-essential pkg-config qt4-qmake libqt4-dev libavformat-dev libavcodec-dev libavutil-dev libswscale-dev libasound2-dev libpulse-dev libjack-jackd2-dev libgl1-mesa-dev libglu1-mesa-dev libx11-dev libxfixes-dev libxext-dev libxi-dev g++-multilib libx11-6 libxext6 libxfixes3 libxfixes3:i386 libglu1-mesa:i386
$ cd ssr-master 
$ ./simple-build-and-install 

Bueno, pues me dio algunos errores en la primera compilación. Así que hice lo que pone en la página indicada:

$ cd /usr/lib/i386-linux-gnu
$ sudo ln -s libGL.so.1 libGL.so
$ sudo ln -s libGLU.so.1 libGLU.so
$ sudo ln -s libX11.so.6 libX11.so
$ sudo ln -s libXext.so.6 libXext.so
$ sudo ln -s libXfixes.so.3 libXfixes.so
$ sudo ldconfig
$ cd ~/ssr-master
$ ./simple-build-and-install  

De nuevo me dió error. Viendo mejor el error de compilación me encuentro con que se queja de que no encuentra un tipo de datos llamado AVPixelFormat. Una breve búsqueda en Google me dice que AVPixelFormat es de Jessie, que en Wheezy es PixelFormat, asi que busco en el código todas las apariciones:

$ cd ~/ssr-master/src
$ grep -irl AVPixelFormat * 

Y voy fichero por fichero fuente cambiando AVPixelFormat por PixelFormat. Podría haberlo hecho automáticamente mediante sed, pero tampoco eran muchos cambios. Una vez acabado, lanzamos de nuevo el proceso:

$ cd ~/ssr-master
$ ./simple-build-and-install  

Y ahora si compilaba. Al acabar nos pide contraseña del usuario para ejecutar con sudo la instalación y tachán... en unos instantes está todo instalado.

Indagando un poco sobre la instalación veo que ha copiado los siguientes ficheros:

  • El ejecutable: /usr/bin/simplescreenrecorder 
  • Las librerias:  /usr/lib/i386-linux-gnu/libssr-glinject.la y /usr/lib/i386-linux-gnu/libssr-glinject.so, haciendo un "ldconfig -n /usr/lib/i386-linux-gnu" después.
  • El fichero .desktop: /usr/share/applications/simplescreenrecorder.desktop, haciendo un update-desktop-database después para añadirlo al menú del entorno gráfico (en mi caso XFCE).
Y con esto ya está instalado. Desde el menú o desde terminal podemos ejecutar simplescreenrecorder  y se nos carga la ventana de inicio para empezar el asistente de grabación de Escritorio:


Despúes me planteé copiarlo a otras máquinas. Como todavía no me he puesto en serio a hacer paquetes Debian un poco mas complejos de lo normal, con dependencias y scripts de postinstalación  (a ver si me pongo a aprenderlo y así puedo contarlo aquí) pensé en hacer un script bash de instalación para automatizarlo un poco, pero antes me dió por copiar el ejecutable /usr/bin/simplescreenrecorder  a una máquina cualquiera y probarlo allí: carajo, funcionaba. No tengo ni idea de para que son las librerías (aunque supongo que será para integrar la funcionalidad de grabación en aplicaciones que compilemos nosotros), pero no son necesarias: con el ejecutable es suficiente.

Aquí va un enlace al ejecutable para Debian Wheezy de 64 bits, por si alguien quiere instalarlo de una forma rápida y sucia. Para ejecutarlo solo habría que abrir un terminal y lanzarlo desde allí. Si da algún error seguramente sea porque no encuentra alguna librería (fichero .so) que necesite el programa y no la tienes en tu sistema. La solución es sencilla: averigua a que paquete pertenece buscando en Internet e instálala.

Bueno, pues otro día seguimos con mas cosas.


viernes, 9 de octubre de 2015

Un blog de andar por casa

Hasta hace poco tenía recopilada información y enlaces sobre el centro en una intranet constituida por páginas web, con una estética directamente salida de los 90 que daba vergüenza ajena. Recolocando cosas me planteé buscar un CMS/Blog sencillo que pudiese montar en poco tiempo para organizar todo ese contenido y permitir la publicación sencilla y rápida de nueva información dentro de la intranet.

El objetivo era encontrar algo ligero, que no necesitase ningún extra para funcionar: ni base de datos, ni librerías, ni entornos de servidor (tipo Tomcat o algún otro monstruo hecho en Java que esté de moda ahora). Sorpresivamente me encontré una gran abundancia de sistemas de este tipo y páginas con recopilaciones como estas:
Al final, abrumado ante tanta oferta me decanté por NibbleBlog, por varias razones:
  • Para instalar simplemente se necesita descomprimir el fichero zip en /var/www/.... dentro de un servidor con Apache y PHP5 y poco más.
  • Tiene un pequeño conjunto de temas fáciles de aplicar y retocar.
  • Tiene un pequeño conjunto de plugins también sencillos instalar y adaptar si te manejas en php.
  • Los posts y las páginas publicadas se guardan en ficheros planos XML, fáciles de mantener.
La instalación es tan sencilla como bajar el .zip y descomprimirlo dentro dela ruta /var/www/.... del servidor elegido, que suponemos tendrá instalado apache2 y php5. El resultado final será este:









Tenemos una zona de publicación de posts a la derecha y a la izquierda 4 apartados fijos:
  • Una colección de enlaces permanentes. Me gustaría ser mas discreto pero la he puesto en colores chillones para que sea fácil de identificar.
  • Una serie de enlaces a páginas fijas dentro del CMS, con posts que siempre se podrán consultar.
  • Un listado con los títulos de los ultimos posts.
  • Un buscador dentro del CMS/Blog.
En el área de administración entramos con un usuario y contraseña definidos en la primera entrada al mismo, tras la instalación. La ruta para entrar en el panel de administrador es http://servidor.que.sea/carpeta-donde-esta-el-blog/admin.php.
:


Una vez dentro vemos el pequeño conjunto de opciones de configuración que hay:



Una para la publicación de posts/creación de páginas fijas/subida de vídeos, con un editor de HTML sencillo pero muy completo.



Un apartado para administrar todo lo que se ha publicado:

Un apartado para la típica configuración general del CMS:



Otro apartado para elegir el tema. Vienen 4 o 5 instalados de serie, pero se pueden instalar mas desde su página/foros, simplemente hay que bajarlos y meterlos en la carpeta themes de la ruta donde descomprimimos el zip de instalación. Yo he elegido el tema "Echo", aunque luego he tuneado un poco sus CSS .



Por último, también tenemos un apartado para añadir los plugins. Al igual que los temas, vienen varios por defecto y es fácil añadir nuevos plugins descargados de su página/foros.  En la configuración de cada plugin siempre hay un "número de orden" que nos permite definir  en que orden (de arriba a abajo) se colocarán en la parte izquierda de la pantalla. Los plugins están en PHP y son bastante fáciles de modificar.


Un plugin muy interesante es HTML Code, que permite meter código HTML arbitrario. Yo lo he usado por ejemplo para crear el menú de enlaces multicolor de la izquierda.


Y ya está, con esto he conseguido dar algo mas de glamour a una página que ve a diario todo el mundo en el centro, ya que como buen tirano tengo puesta su apertura automática al abrir sesión en el autostart de los Linux y la carpeta Inicio de los Windows.

Nos vemos pronto...