Jon Lord: La clase del señor Purple.

Hace dos años el cáncer nos dejaba sin el enorme Jon Lord, uno de los superclase del rock and roll, pura elegancia tras su órgano Hammond. El mejor teclista que haya visto el rock and roll (apreciación totalmente personal pero que considero un axioma) como demostró con Deep Purple, Whitesnake y en sus diversos proyectos en solitario. Como decía un amigo mío, «el señor Purple»

Llamar a procedimientos almacenados en PHP

Una entrada que llevaba mucho tiempo en el TODO list, sobre trabajar con procedimientos almacenados con PHP.

Para empezar vamos a plantear un escenario en el que tenemos tres procedimientos almacenados en MySQL (dos selects y un insert) contra una tabla llamada productos, que tiene tres campos (id como clave primaria, descripcion con una descripción del producto, precio con un valor numérico decimal).

El SP de la primera select, que nos devuelve la descripción y el precio del producto según su id, sería este:

CREATE PROCEDURE getProducto(IN id_val INT) 
  BEGIN 
    SELECT descripcion, precio from productos WHERE id = id_val; 
  END;

El SP de la segunda select, que nos devuelve la descripción y el precio todos los productos, por lo que no recibe parámetros:

CREATE PROCEDURE getAllProductos() 
  BEGIN 
    SELECT descripcion, precio from productos ; 
  END;

Y el sp del insert sería este, al que le pasamos los tres valores a meter:

CREATE PROCEDURE addProducto(IN id_val INT,descripcion_in varchar(50), precio_in float) 
  BEGIN 
    INSERT INTO productos VALUES (id_val, descripcion_in, precio_in);
  END;

Bueno, ya tenemos nuestro escenario, entonces ¿cómo hacemos para llamar a estos procedimientos desde nuestro código php? Pues simplemente lanzamos una consulta en la que llamamos a la instrucción CALL de MySQL para que ejecute el procedimiento almacenado que le digamos con los parámetros que tocan.

/*Empezamos con el procedimiento de inserción*/
/*Lo primero es crear un objeto mysqli*/
$mysqli = new mysqli("servidor", "usuario", "pass", "db");

/*Y llamamos al procedimiento para hacer la inserción*/
/*Si falla imprimimos el error*/
if (!$mysqli->query("CALL addProducto(1001, 'Nueces de Macadamia', 12.23)")) {
    echo "Falló la llamada: (" . $mysqli->errno . ") " . $mysqli->error;
}

La propia función query del objeto mysqli nos devolverá TRUE si no viene con errores y FALSE si pasa algo inesperado.

¿Y qué pasa con la recuperación de datos? Ahí nos vamos a un terreno más pantanoso. Para una consulta con un solo resultado no es problema:

/*Empezamos con el procedimiento de recuperación de una fila*/
/*Lo primero es crear un objeto mysqli*/
$mysqli = new mysqli("servidor", "usuario", "pass", "db");

/*Y llamamos al procedimiento para recoger los datos*/
/*Si falla imprimimos el error*/
if (!($res = $mysqli->query("CALL getProducto(1001)"))) {
    echo "Falló la llamada: (" . $mysqli->errno . ") " . $mysqli->error;
}

/*E imprimimos el resultado para ver que el ejemplo ha funcionado*/
var_dump($res->fetch_assoc());

Pero claro, en este caso podemos hacerlo así porque esperamos un solo resultado, pero si esperamos varias filas la cosa es distinta ya que mysqli->query() devuelve sólo el primer conjunto de resultados. Tenemos dos alternativas para esta situación: mysqli_real_query() o mysqli_multi_query(). En el ejemplo usaremos la segunda, y veremos también la forma de recorrer este resultado:

/*Empezamos con el procedimiento de recuperación de una fila*/
/*Lo primero es crear un objeto mysqli*/
$mysqli = new mysqli("servidor", "usuario", "pass", "db");

/*Y llamamos al procedimiento para recoger los datos*/
/*Si falla imprimimos el error*/
if (!$mysqli->multi_query("CALL getAllProductos()")) {
    echo "Falló la llamada: (" . $mysqli->errno . ") " . $mysqli->error;
}

/*Ahora con este bucle recogemos los resultados y los recorremos*/
do {
    /*En el if recogemos una fila de la tabla*/
    if ($res = $mysqli->store_result()) { 
        /*Imprimimos el resultado de la fila y debajo un salto de línea*/
        var_dump($res->fetch_all());
        printf("\n");
        /*La llamada a free() no es obligatoria, pero si recomendable para aligerar memoria y para evitar problemas si después hacemos una llamada a otro procedimiento*/
        $res->free();
    } else {
        if ($mysqli->errno) {
            echo "Store failed: (" . $mysqli->errno . ") " . $mysqli->error;
        }
    }
} while ($mysqli->more_results() && $mysqli->next_result());
/*El bucle se ejecuta mientras haya más resultados y se pueda saltar al siguiente*/

Añadiré a esto que también es posible utilizar las llamadas a procedimientos almacenados usando sentencias preparadas, procediendo del modo habitual a la hora de pasar los parámetros.

¿Cómo conocer nuestra IP externa?

¿Conocéis ese momento incómodo en que tenéis que hacer una conexión para ayudar a alguien por remoto y el TeamViewer os mira mal y os dice «nanay, chaval, esto es uso comercial descarado«? Tras el pánico inicial toca recurrir a VNC, que es verdaderamente libre (otra opción sería pagar TeamViewer o buscar alguna alternativa más, pero asumamos que no pensáis soltar un duro). ¿Problemilla? Que para realizar una conexión por VNC necesitamos (además de abrir algunos puertos) conocer nuestra IP externa. Un ifconfig en Linux o un ipconfig en Windows sólo nos dará nuestra ip dentro de la red local, y en este caso necesitamos saber qué ip usamos hacia el exterior.

Una solución rápida y fácil es recurrir a alguna de estas webs, que directamente nos darán el resultado:

Evitar la desconexión automática de las unidades de red en Windows 7

Esta mañana me encontraba una incidencia de un cliente a primera hora, se quejaba de que un programa que utilizaba debía cargar una radiografía desde una unidad de red compartida, pero que los equipos, Windows 7 Home, tras un rato fuera de uso dejaban de tener accesibles estas unidades. Basta un simple doble click para activarlas otra vez, pero eso implica salir del programa y repetir todas la operación, una cuestión engorrosa.

¿Existe una solución para esto? Sí, desde luego. Esta desconexión automática ocurre a los 30 minutos y este tiempo puede modificarse, ampliándose, reduciéndose y hasta desactivándose. Lo que tenemos que hacer es abrir la línea de comandos con permisos de administrador (Inicio-> Todos los programas-> Accesorios-> Click derecho sobre Símbolo del sistema, y ahí elegir Ejecutar como administrador.)

¿Lo podemos cambiar para que en vez de cada media hora ocurra cada hora y media? Basta poner el número de minutos en 90:

net config server /autodisconnect:90

¿Y para desactivarlo?

net config server /autodisconnect:-1

Ojo, para desactivar la desconexión es -1, como pongo arriba, hay gente que lo pone a 0 y entonces no sólo no la desactivan sino que se desconectan a los pocos segundos

Puede haber más motivos para la desconexión, como que el servidor los desconecte por su propia configuración o que el equipo se ponga en suspensión por ahorro de energía (desconectando incluso la tarjeta de red) así que si tras aplicar este comando siguen desconectándose revisad las opciones de energía y la configuración del servidor. Esta solución es válida para los equipos con XP, Vista y Windows 7, no tengo información de si va igual en Windows 8, y no valdría para los anteriores a XP (si alguien los conserva).

«Poor Man’s VPN» sobre tunel SSH

Partamos de uno de estos supuestos:

  1. Estás conectado a una red de cuya seguridad no te fías, pero tienes un servidor seguro en algún sitio al que podrías conectarte.
  2. Estás en una red con conectividad limitada, pero puedes conectarte a un servidor con salida a internet

¿Tienes una opción para conectarte de forma segura? Sí. Puedes hacer una llamada «poor man’s VPN» sobre un tunel SSH ¿Cómo hacemos esto? Bueno, lo primero es que el servidor contra el que vamos a conectarnos tenga habilitados tanto la posibilidad de hacerse root de forma remota como la posibilidad de tunneling y la redirección de puertos. Todo esto lo podéis poner a funcionar en el archivo /etc/ssh/sshd_config, poniendo PermitRootLogin yes y PermitTunnel yes y luego reiniciando el servicio sshd (suponiendo que trabajéis con un servidor Linux, claro). Por seguridad podéis (deberíais) configurar unas claves SSH

Una vez esté todo eso habilitado toca empezar a configurar el cliente (vamos de nuevo con Linux) desde el que queremos conectarnos. Necesitamos saber la IP del servidor al que nos conectamos, en el ejemplo vamos a poner una ficticia que sería 83.112.23.4X. La máscara de red también tiene que ser la pertinente para vuestra configuración de conexión:

#abrimos un tunel ssh al servidor (vosotros poned la IP de vuestro server)
sudo ssh -f -w any 83.112.23.4X true

#asignamos una ip al tunel (ip local típica, en vuestro caso la que corresponda asegún la configuración)

sudo ifconfig tun0 192.168.0.2 192.168.0.1 netmask 255.255.255.0

Tras esto es necesario tener configurado el tunel en el servidor

# la misma asignación que en el server, pero invirtiendo las ip's de los dos puntos del tunel
sudo ifconfig tun0 192.168.0.1 192.168.0.2 netmask 255.255.255.0

# habilitamos el reenvío de paquetes
echo 1 > /proc/sys/net/ipv4/ip_forward

# habilitamos el enmascaramiento
sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE

Finalmente toca acabar de configurar el enrutamiento en el cliente, en este ejemplo la puerta de enlace será 10.1.1.1, para vuestra configuración usad la que toque. La cosa es borrar la ruta previa a la puerta de enlace para usar la del tunel:

sudo ip route add 10.0.0.0/8 via 10.1.1.1
sudo ip route del default via 10.1.1.1 dev eth0
sudo ip route add default via 192.168.0.2

Ya sólo te queda comprobar si la conexión está funcionando bien.

Liberar espacio en /boot para instalar actualizaciones en Ubuntu 14.04

Hoy mi Ubuntu (14.04 LTS) me pedía una actualización, pero al intentar descargarla me avisaba de que no había espacio en /boot para descargarlas. No era la primera vez la verdad, ocurre cuando se acumulan viejas versiones del Kernel que se descargan para las actualizaciones y que ya no son necesarias. Si alguna vez os pasa podéis recurrir al terminal para «ahuecar» un poco de espacio, no es complicado para nada, basta con copiar las instrucciones que os dejo:

#Lo primero es coseguir permisos para ejecutar como root las instrucciones
sudo -i

#ahora toca ejecutar todo este churro
#básicamente creará un documento con todos los archivos de imagen viejos
#y luego lo recorrerá borrándolos
dpkg --get-selections|grep 'linux-image*'|awk '{print $1}'|egrep -v "linux-image-$(uname -r)|linux-image-generic" |while read n;do apt-get -y remove $n;done 

#y finalmente aplicamos el autolimpiado de apt-get
#para dejar bien limpia la caché
sudo apt-get autoclean

Goodbye, Tuco

Con 98 años hoy nos deja Eli Wallach, actor que debutó en 1956 de la mano del gran Elia Kazan y que se mantuvo activo hasta los 95 años (en 2010 filmó 3 películas). En su ficha de IMDB encontramos 167 entradas como actor, dándonos una muestra de lo prolífica que fue su carrera. Durante los 60 apareció en varios westerns caracterizado como un personaje de ascendencia mexicana, siendo recordado principalmente por su interpretación de Tuco, el feo de El Bueno, El feo y el Malo, el legendario western de Sergio Leone donde compartía protagonismo con Clint Eastwood y Lee Van Cleef. Como detalle friki, él era Mr Freeze en la serie de Batman de los 60.

Un gran actor que se nos va, DEP Eli Wallach, adiós Tuco.

Cifrar nuestro tráfico con DNSCrypt

El cifrado del tráfico entre nuestro equipo y el ISP es una medida de seguridad que nos permitirá protegernos de ataques Man in the Middle, de intentos de espiar nuestras comunicaciones y dificultará al ISP la posibilidad de aplicarnos algunas restricciones (ahora que la neutralidad de la red está en peligro).

Nuestra solución segura será usar DNSCrypt, un software disponible para Windows, Linux, BSD, Android, iOS y OSX. Aquí nos ocuparemos de la instalación en Linux. Como no existe ningún paquete .deb, .rpm o repositorio que podamos utilizar para instalarlo nos tocará compilar el código fuente. Como paso previo, pues, tendremos que tener en el equipo los paquetes necesarios para instalar. En los linux de la familia Debian lo amañamos con un

sudo apt-get install build-essential

Luego tocará descargar la librería libsodium, una librería necesaria para la compilación:

tar -xvzf libsodium-0.5.0.tar.gz
cd libsodium-0.5.0
./configure
make

make check  ##esto verificará si está todo en orden

sudo make install

El siguiente paso es descargar ya el código de DNSCrypt, descomprimirlo y compilarlo

sudo ldconfig #necesitamos lanzar esta configuración primero

tar -xvzf dnscrypt-proxy-1.4.0.tar.gz
cd dnscrypt-proxy-1.4.0
./configure
make

sudo make install

Muy bien, DNSCrypt está instalado, lo siguiente es configurarlo. Nos vamos a editar nuestra conexión de red y en la configuración de IPv4 elegimos en el campo Método la opción Sólo direcciones automáticas (DHCP) y en el campo Servidores DNS ponemos la dirección 127.0.0.1 (si os da problemas al probarlo cambiad por, por ejemplo, 127.0.0.2). Después desde el terminal ejecutamos restart network-manager. Tras hacer esto nos quedaremos sin conexión a internet ya que hemos desconfigurado las DNS y hasta que no se ejecute DNSCrypt no volverán a estar funcionales. Por tanto, lo ejecutamos:

/usr/local/sbin/dnscrypt-proxy --daemonize --pidfile=/run/dnscrypt-proxy.pid --edns-payload-size=4096

Para comprobar que todo funciona prueba a entrar en http://www.opendns.com/welcome/ para ver que la conexión ha vuelto. Como ya dije arriba es posible que usando 127.0.0.1 falle, así que si os pasa matáis el proceso de DNSCrypt, cambiáis la IP por, por ejemplo, 127.0.0.2 y volvéis a lanzar DNSCrypt añadiendo esa dirección como parámetro tal que así:

/usr/local/sbin/dnscrypt-proxy --daemonize --pidfile=/run/dnscrypt-proxy.pid --edns-payload-size=4096 --local-address=127.0.0.2

Ahora vamos con un último paso ¿quieres que DNSCrypt se ejecute cada vez que iniciamos el sistema? Si estás en un sistema basado en Debian toca modificar el archivo /etc/rc.local y pegamos, justo antes de la instrucción exit 0 una de las siguientes líneas:

#en caso de que utilicéis la ip 127.0.0.1
exec /usr/local/sbin/dnscrypt-proxy --daemonize --pidfile=/run/dnscrypt-proxy.pid --edns-payload-size=4096

#en caso de la 127.0.0.2
exec /usr/local/sbin/dnscrypt-proxy --daemonize --pidfile=/run/dnscrypt-proxy.pid --edns-payload-size=4096 --local-address=127.0.0.2

En la documentación de DNSCrypt podéis leer más opciones sobre parámetros, resolución de problemas, cambiar OpenDNS por un DNS alternativo…

Ralentizando el acceso a determinadas páginas mediante Squid

Cuando uno administra una red corporativa se topa con algunos usuarios que hacen un uso inadecuado de la misma. No pasa nada porque de vez en cuando algún usuario entre a revisar si tiene un mail en su cuenta personal, un mensaje en facebook o a twittear una cosa, pero otros se tiran la mañana. Me se de alguno que usaba la red corporativa del hospital en el que trabajaba para descargarse gigas de discos de metalcore. Cuando la gente se pone a tirar de youtube, u otros servicios de vídeos o música, además puede consumirte bastante ancho de banda que podría ser necesario para otros menesteres.

Cortar completamente el acceso a estas webs es una solución, pero ¿es la mejor solución? Lo primero es que generará malestar en los trabajadores y mal rollo entre estos y el administrador, y sembrar discordias en un centro de trabajo nunca es una buena idea. Además ¿por qué castigar por igual al que mientras se toma el café de media mañana entra a colgar una foto de un gato jugando con un iPad que al que se ha tirado dos horas leyéndose de pe a pa la web de Marca? Hoy vamos a ver como usar las Delay Pools de Squid para solucionar esto.

Delay Pools nos permite ralentizar la velocidad de navegación de ciertos usuarios o hacia ciertos sitios (o ambas a la vez). Esto hará que el procastinador desista de su idea.

Como es obvio para poder hacer esto necesitamos que los usuarios naveguen por medio de un proxy, donde tendremos instalado Squid para controlar el tráfico y acceso a según qué páginas. Si has instalado Squid desde repositorio ya vendrá con soporte para Delay Pools, si ha sido una compilación propia entonces asegúrate de que lo tenga.

Con la instalación comprobada vamos al siguiente paso: en la carpeta /etc/squid/ (o /etc/squid3 si usas esa versión) creamos un archivo con la lista de todas las ip’s que queremos ralentizar, para el ejemplo el archivo se llamará «vaiamodo» (en gallego «ve despacio»).

Cuando tengamos el archivo con la lista de las ip a ralentizar tocará editar el archivo squid.conf, que te encontrarás dentro de /etc/squid/ (o /etc/squid3, repito, si usas esa versión) para hacer varias cosas:

Lo primero, crear una lista de control de acceso (acl) con el contenido de la lista de ip que hemos bautizado como vaiamodo, acl que llamaremos ralentizar. Luego establecemos el ancho de banda para el Delay Pools, que será de 1, que es el mínimo posible. Tras eso creamos una regla llamada capar que hará que las Delay Pools actúen sobre las url que coincidan con una expresión regular concreta (en este caso frenaremos varias webs populares y además todas las url que tengan la palabra «watch» ya que suele ir ligada a sitios donde ver vídeos). Finalmente ordenaremos que los usuarios de la primera regla vayan más lentos en la páginas definidas en la segunda. El ejemplo para Squid2 escrito es así:

acl ralentizar src "/etc/squid/vaiamodo"
delay_pools 1
delay_class 1 1
delay_parameters 1 1000/100
acl capar url_regex -i vimeo
acl capar url_regex -i watch?
acl capar url_regex -i youtube
acl capar url_regex -i youtu
acl capar url_regex -i facebook
acl capar url_regex -i twitter
acl capar url_regex -i marca

delay_access 1 allow capar ralentizar

Con esto haremos que su velocidad de conexión sea tan lenta que las páginas en cuestión sean innavegables para ellos porque cargarán a 1kbps.

Hay que tener en cuenta que podrías tener que cambiar algo en la configuración si ya estás usado control de navegación por listas blancas o si los usuarios en vez de por la ip acceden por LDAP o algún otro sistema de autentificación.

NBA 2013-2014: La temporada en 10 memes

Además de disfrutar como un enano con la victoria de los Spurs, no por ser un gran seguidor de San Antonio sino por la victoria de un modelo de baloncesto, un estilo basado en el juego en equipo frente a la individualidad, otra cosa con la que este año me he echado unas risas durante la temporada NBA ha sido con los múltiples Memes que páginas como la comunidad de Facebook NBA memes o la web Hypun nos regalaron todo el año. Así que he decidido usar 10 de estos memes para resumir la temporada:

The Return Rose
Tras un año en blanco regresó Rose… para volver a romper
Kobe's failed return
Kobe también volvía de su lesión… y a los pocos partios «out» otra vez
Ref Crawford
Las ayudas arbitrales a los Heat sembraron polémica durante la temporada
Worst Lakers
Este año vimos a los peores Lakers desde que están en LA
Game 7 Everywhere
También vivimos una primera ronda de PO igualada, muchos séptimos partidos hubo.
Las declaraciones racistas de Sterling sacudieron la liga y acabaron llevando a su expulsión de la misma.
Las declaraciones racistas de Sterling sacudieron la liga y acabaron llevando a su expulsión de la misma.
Hibbert 0 0
All Star y varias nominaciones en quintetos, pero Hibbert hizo un PO nefasto, con varios partidos de 0 puntos
Mallory Edens & Kevin Durant
Durant dedicó el MVP a su madre y la frase dejó muchos memes. También lo hizo la guapa hija del propietario de los Bucks, que asistió al sorteo del Draft repesentando a la franquicia
Spurs campeones 2014
Mejor balance en liga regular y título con victoria aplastante en la final ¿Viejos?
Kawhi MVP
Pocos apostamos por Kawhi, pero siempre dije que ese chaval llegaría lejos. MVP de la final con 22 años.

Y ahora a esperar hasta finales de octubre para una nueva campaña. Nos queda el draft (parece que el físico del prometedor Embiid presenta dudas), el mercado (¿dónde irá Pau? ¿quién fichará a Love? ¿LeBron seguirá en Miami?), el mundial de basket… tenemos basket para rato.