Error al cambiar el contexto SELinux de un archivo

Supongamos que quieres cambiar el tipo de un archivo así:

$ chcon --type svirt_sandbox_file_t somefile

Y que te da el siguiente error:

chcon: fallo al cambiar el contexto de «somefile» a «unconfined_u:object_r:svirt_sandbox_file_t:s0»: Operación no permitida

Para corregirlo, comprueba 3 cosas:

  1. ¿Tienes permiso de escritura sobre el archivo? (ls -l somefile)
  2. ¿El archivo tiene el atributo i (inmutable)? (lsattr somefile)
  3. ¿SELinux está activado? (getenforce)

¿Qué significa t-ignore=”True” en Qweb (Odoo)?

La etiqueta t-ignore en una definición de una vista Qweb en Odoo sirve para indicar que los cambios que efectúe el usuario en dicho nodo deben ignorarse. Suele aplicarse a los campos referentes a datos de la empresa principal, ya que estos provienen de la base de datos y no deben guardarse literalmente como el XML de la vista.

Cómo compilar automáticamente Sass en Odoo

El tutorial de cómo crear un tema para Odoo te explica cómo usar LESS como preprocesador de CSS.

Está bien, pero si te gusta programar en Python, probablemente te guste más Sass que LESS por su sintaxis (y quizá por otras razones). Pues bien, website_less también permite compilar Sass (y SCSS) automáticamente.

Para activar LESS:

$ yum -y install npm
$ npm install -g less less-plugin-clean-css

Para activar Sass:

$ yum -y install rubygems ruby-devel
$ gem install bootstrap-sass compass sass

Las instrucciones son para CentOS 7, pero para cualquier otra distro, simplemente busca los paquetes equivalentes.

Con esto debería bastar, pero es posible que tras hacerlo te salgan errores como el siguiente al intentar compilar Sass:

WARNING demo openerp.addons.website_less.ir_qweb: /usr/share/rubygems/rubygems/path_support.rb:68:in `path=': undefined method `+' for nil:NilClass (NoMethodError)
 from /usr/share/rubygems/rubygems/path_support.rb:30:in `initialize'
 from /usr/share/rubygems/rubygems.rb:357:in `new'
 from /usr/share/rubygems/rubygems.rb:357:in `paths'
 from /usr/share/rubygems/rubygems.rb:379:in `path'
 from /usr/share/rubygems/rubygems/specification.rb:794:in `dirs'
 from /usr/share/rubygems/rubygems/specification.rb:658:in `each_normal'
 from /usr/share/rubygems/rubygems/specification.rb:669:in `_all'
 from /usr/share/rubygems/rubygems/specification.rb:822:in `each'
 from /usr/share/rubygems/rubygems/specification.rb:864:in `find'
 from /usr/share/rubygems/rubygems/specification.rb:864:in `find_inactive_by_path'
 from /usr/share/rubygems/rubygems.rb:175:in `try_activate'
 from /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:132:in `rescue in require'
 from /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:144:in `require'
 from <internal:abrt_prelude>:2:in `<compiled>'
 This error occured while compiling the bundle 'website.assets_frontend' containing:
 - /<theme_module>/static/src/css/style.sass

Esto ocurrirá en caso de que el usuario que corre Odoo (normalmente llamado también odoo) no tenga un $HOME. Hay que crearlo para que todo funcione:

$ mkdir /home/odoo
$ chown odoo:odoo /home/odoo

Otra opción es asignarle al usuario una $HOME que ya exista:

$ usermod --home /var/lib/odoo odoo

Cómo juguetear con Linux y no morir en el intento

Conozco gente a quien le encanta Linux, pero que siempre está reinstalándolo porque se lo ha cargado intentando hacer algo que no sabía muy bien cómo hacer. Quizá un manazas que se cree está aprendiendo a ser un manitas, o quizá simplemente le guste hackear cosas. Aquí va una breve guía para quienes están en esa situación (y empiezan a hartarse).

Haz las pruebas en una máquina virtual

Todas las distribuciones Linux vienen con alguna herramienta de virtualización. Quizá la mejor en relación sencillez/funcionalidad sea VirtualBox, aunque también tenemos virt-manager para quienes necesiten más funcionalidades o Cajas para quienes necesiten más sencillez.

Si vas a empezar a trastear sin saber muy bien si va a funcionar, siempre es mejor hacer las pruebas en un entorno virtual, el cual puedes restaurar a una versión anterior con dos clicks, o eliminar y re-crear con otros dos. Tu máquina anfitriona seguirá intacta, sin importar cuánto destroces la virtual.

Crea un usuario limitado para las pruebas

Esta es otra alternativa a la máquina virtual, para cuando necesitas hacer pruebas en un entorno real para no perder rendimiento. Quizá si tienes que instalar un juego o algo así…

Realmente es muy difícil que un usuario sin permisos de superusuario pueda llegar a cargarse una instalación Linux, o siquiera cualquier cosa que no sea su $HOME, así que créate un usuario para las pruebas y no te permitas usar sudo desde esa cuenta.

Si algo sale mal, eliminas el usuario, eliminas su carpeta, lo vuelves a crear, y asunto arreglado.

Si sale bien, coges lo que has hecho, te lo copias a la $HOME de tu usuario normal, le haces un chown, y eliminas el usuario de pruebas y su carpeta.

Instala todo el software en paquetes

Evita ante todo instalar software que no venga empaquetado.

  1. Busca los paquetes para tu distribución.
  2. Si no hay, busca para otra distribución que use tu misma paquetería.
  3. Si no hay, busca para otra distribución que use paquetería distinta, y transfórmalo a la de tu distribución con herramientas como alien.
  4. Si no hay, crea tu propio paquete. No es muy diferente de compilar a mano, pero se hace todo automáticamente y es más fácil actualizar, desinstalar y encontrar errores en la compilación.

Puedes mirar el tutorial que hice hace tiempo de cómo empaquetar en RPM. De entrada te diré que para hacer un RPM sólo necesitas el código fuente del programa y un fichero de texto en el que le das las órdenes para que lo compile e instale.

Como nota adicional, los paquetes RPM forman parte del LSB. Para entendernos: toda distribución Linux debe permitir instalar paquetes RPM (aunque sea mediante convertidores) para ser considerada oficialmente una distribución Linux, de modo que son un buen lugar para empezar.

Instala los servidores en Docker

Docker es, quizá, la tecnología más influyente que ha surgido el año pasado. Permite crear servidores de la forma más fácil posible, y redistribuirlos igual de fácil.

Si vas a instalar un servidor de lo que sea, busca en hub.docker.com, y si hay una imagen oficial (o al menos confiable) instálalo desde ahí.

No es el objetivo de esta entrada enseñarte a usar Docker, pero te garantizo que si administras sistemas (en definitiva, si todo lo que has leído hasta ahora no te suena a chino), aprender a usarlo será el tiempo mejor invertido de toda tu carrera.

Usa control de versiones para guardar los cambios de /etc

En /etc es donde se almacenan las configuraciones para todos los servicios del sistema. A veces no hay más remedio que cambiar alguna, así que es bueno que tomes la costumbre de usar algún sistema de control de versiones (como Git o Mercurial) para no perder el rastro de los cambios que hagas.

Todo el software no empaquetado va en /usr/local

Si por algún motivo todos los consejos de arriba no te son suficientes, toma este último: el prefijo /usr/local en las distribuciones Linux se utiliza para colocar el software que no viene empaquetado en ningún sitio y que sólo está disponible localmente en tu máquina.

/usr/local tiene a su vez subdirectorios similares a los mismos que tiene /usr, pero el administrador del sistema ya sabe que todo lo que haya ahí no va empaquetado.

También está el prefijo /opt para cuando el software viene en un paquete difícil de encajar en la estructura de /usr/local. Es habitual que se usen subdirectorios de /opt para poner el programa, y se vinculen con ln -s los binarios en /usr/local/bin.

Puedes repasar el Filesystem Hierarchy Standard si te estás liando.

En resumen: si tienes que instalar cosas a mano, nunca te salgas de /usr/local ni /opt.

Conclusión

Estos son simplemente algunos principios que creo que podrán ayudarte a no cargarte tu instalación cada semana. De todas formas, algo puede salir mal, así que no te desesperes. Si no me hubiera pasado a mí cientos de veces, no habría podido darte todos estos consejos, así que ¡a reinstalar! La próxima vez saldrá mejor. ;)

Cómo restaurar la fecha (aproximada) a las fotos de WhatsApp

Una de las cosas más curiosas que suceden hoy en día es que la gente se pelea por tener un teléfono con más megapíxeles que nadie, para luego mandar las fotos por WhatsApp y que pierdan toda su calidad.

Ironías aparte, lo que más me fastidia de todo en realidad es que WhatsApp le quita los metadatos EXIF a las imágenes.

¿Para qué sirven los metadatos EXIF?

Contienen un montón de información valiosa para los amantes de la fotografía, o para cualquiera que guste de organizarse bien su colección de fotos:

  • Cámara con que se tomó.
  • Coordenadas GPS de dónde se tomó.
  • Fecha en que se tomó.
  • Etc.

Con esos datos, puedes comparar qué tal saca las fotos tal o cual cámara o teléfono, y así no llevarte sorpresas si lo compras.

También (lo que más me interesa para esta entrada), un programa de organización de colecciones de fotos puede usar la fecha para organizarte las fotos automáticamente, o la ubicación para pintártelas en un mapa.

¿Qué pasa cuando le quito la fecha a las imágenes?

Programas como Shotwell ya no son capaces de determinar en qué fecha se tomó la imagen, así que no te la pueden organizar.

Por otro lado, resulta imposible determinar en qué fecha y hora exactas se tomaron, pero hay algo que todavía nos puede valer: la fecha de última modificación del fichero. Normalmente coincidirá con la fecha en que WhatsApp grabó la foto en tu teléfono.

Cómo grabar la fecha de última modificación en EXIF

He colgado un script llamado ctime2exif.sh que te servirá para eso.

Antes de usarlo, crea una copia de seguridad de las imágenes, por si algo sale mal. Copiarlas a otro directorio debería bastar.

Recuerda que puedes descargarlo y ejecutarlo con un solo comando:

$ curl --silent https://bitbucket.org/api/2.0/snippets/yajo/k75k/tip/files/ctime2exif.sh | bash /dev/stdin *.jpg

Ya tendrás tus fotos listas para organizar con Shotwell.

Cómo forzar la instalación de documentación con yum/dnf

La imágen oficial de CentOS para Docker viene preconfigurada para no instalar la documentación al instalar paquetes. Puedes comprobarlo con:

$ docker run --rm centos grep tsflags /etc/yum.conf

Verás que te devuelve tsflags=nodocs. La documentación de yum.conf nos explica lo que hace la opción tsflags.

Lo que queremos hacer es deshabilitarla al instalar ciertos paquetes. Por ejemplo CUPS la necesita para mostrar su index.html. Lo instalaríamos así en nuestro Dockerfile:

$ yum --assumeyes --setopt tsflags= install cups

Lo mismo sirve para dnf.

Cómo conectar a una impresora IPP desde Windows

Es posible que tengas un servidor CUPS al que quieras conectar con tu máquina Windows, pero no te sea posible. Veamos cómo hacerlo.

  1. Desde el cliente Windows, ve a Panel de control > Dispositivos e impresoras > Agregar una impresora > Agregar una impresora de red > La impresora deseada no está en la lista > Seleccionar una impresora compartida por nombre.
  2. En la caja de texto, introduce la dirección IPP en formato HTTP. Es decir, la dirección ipp://example.com/printers/impresora1 se transformará en http://example.com:631/printers/impresora1.
    • Si te da un error diciendo que no se puede conectar a la impresora, más abajo te explico cómo solucionarlo.
  3. Escoge el controlador Generic > MS Publisher Imagesetter.

¡Listo! Ya has conectado a tu servidor por IPP.

Claro, hay algunos problemas:

No puedo imprimir a doble cara

Lamentablemente, el controlador MS Publisher Imagesetter es muy básico y no puedes escoger bandejas, ni imprimir a doble cara, etc.

La solución es crear más impresoras virtuales desde CUPS que sean la misma pero con diferentes opciones por defecto, y escoger la que tenga las opciones que necesitas al imprimir.

Por ejemplo, para la impresora a color, puedes tener color-1-cara, color-2-caras, color-bandeja-1, color-bandeja-2, etc.

Esto es un rollo, pero cuando tienes problemas con un controlador (como me pasa a mí con los de HP) esto te sirve para usar un controlador más básico usando CUPS como proxy, y que sea él quien se encargue de la comunicación real con la impresora. En mi oficina, esto ha resucitado varias impresoras.

No puedo conectar a la impresora

Llegados al punto 2, puede que Windows te escupa este error:

Windows no se pudo conectar a la impresora. Compruebe el nombre de la impresora e inténtelo de nuevo. Si es una impresora de red, asegúrese de que la impresora esté encendida y de que la dirección de la impresora es correcta.
Error al agregar impresora IPP a Windows

Probablemente no esté instalado el cliente IPP en tu Windows. La ayuda de Windows nos indica cómo instalarlo:

Para instalar el Cliente de impresión en Internet, siga uno de los métodos siguientes:

  • En Windows 7: en Panel de control, haga clic en Programas y características, haga clic en Activar o desactivar las características de Windows, expanda Servicios de impresión y documentos, active la casilla Cliente de impresión en Internet y, a continuación, haga clic en Aceptar.
  • En Windows Server 2008 R2: en el Administrador del servidor, haga clic en Agregar características, active la casilla Cliente de impresión en Internet y, a continuación, haga clic en Aceptar.

Ahora reinicia el servicio de impresión. Puedes hacerlo desde services.msc o directamente desde la línea de comandos ejecutando:

sc stop spooler && sc start spooler

Por último, vuelve a repetir el tutorial y ahora debería dejarte seguir.

Si aún así no te deja, es posible que haya alguna política de seguridad bloqueando el servidor. Intenta visitarlo desde Internet Explorer (sí, has leído bien), y si te da mensajes de error por zona de confianza, agrégalo a los sitios de confianza.

Cómo usar GVFS para montar unidades de red Samba indicando usuario, dominio y contraseña; o cómo emular entrada de datos manual automáticamente con expect

Un título bien largo, pero es lo que vamos a hacer

Problema

Tengo una unidad de red llamada share en mi servidor de datos de red llamado host que quiero montar usando Samba y GVFS automáticamente, pero al ejecutar:

$ gvfs-mount smb://host/share

Siempre me pide lo siguiente:

User [tu_usuario]:
Domain [WORKGROUP]:
Password:

Y no tengo forma de automatizar eso.

Solución

Expect es un intérprete de órdenes (estilo bash) diseñado para emular a un usuario metiendo datos manualmente. Lo usaremos para montar las unidades automáticamente:

#!/usr/bin/env bash

# Montar unidades emulando a un usuario que mete datos
function mount_share {
    expect <<END
        spawn gvfs-mount $1
        set timeout -1
        expect User
        expect :
        send $2\r
        expect Domain
        expect :
        send $3\r
        expect Password:
        send $4\r
        wait
END
}

# Montar nuestra unidad de red
mount_share smb://host/share usuario dominio contraseña