Category Archives: Temas técnicos

Todo lo que tiene que ver con mi área: computación, gadgets, programación. Recomendada para los que están en el mundo de las computadoras

Reflejar el área maestra en XMonad

Tengo 2 monitores en el trabajo. Mi silla está justo en medio de los 2, por lo que las áreas que más uso para trabajar son la mitad derecha del monitor izquierdo y la mitad izquierda del derecho.  Ahora bien: si han usado XMonad, sabrán que por lo general las áreas maestras de los layout están del lado izquierdo, lo que no me conviene para el monitor de ese lado, pero realmente nunca me había puesto a buscarle solución.

Hoy tuve un buen de ventanas abiertas y estuve revisando datos en todas, pero trabajando en ellos en el área maestra. De repente sentí la necesidad de tener la del monitor izquierdo en la parte derecha y me di a la tarea de investigar qué podía hacer.

Continue reading Reflejar el área maestra en XMonad

Detectando si hay monitor conectado en el puerto HDMI con Haskell

Generalmente hay 2 lugares en donde uso la laptop:

  • En mi escritorio, donde la conecto a un par de monitores, uno de ellos por HDMI).
  • En cualquier otro lugar.

Como uso XMonad, la posición de algunas barras personalizadas varía dependiendo de si estoy usando el monitor de la laptop o el de HDMI. El cambio siempre lo he he hecho manualmente comentando o habilitando un par de líneas en el xmonad.hs, pero quería automatizar el proceso de ser posible. Tenía rato que no usaba Haskell en forma, así que…

Básicamente, lo que necesito es hacer esto en Haskell:

xrandr | grep HDMI1 | cut -d " " -f2

Me eché un clavado en la documentación, y encontré la librería System.Process, concretamente la función createProcess, la cual está definida de la siguiente forma:

createProcess :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)

Donde CreateProcess está definido como se menciona acá:

http://hackage.haskell.org/package/process-1.2.0.0/docs/System-Process.html#t:CreateProcess

Lo que necesito entonces es crear un proceso por cada comando que quiero ejecutar, pero pasar los resultados de uno al siguiente (pipe).  Por tanto, necesito  declarar CreateProcess de la siguiente manera:

Continue reading Detectando si hay monitor conectado en el puerto HDMI con Haskell

Logrotate error en MySQL

Tenía ya tiempo recibiendo a diario esta notificación en los logs:

/etc/cron.daily/logrotate:
error: error running shared postrotate script for /var/log/mysql.log /var/log/mysql/mysql.log /var/log/mysql/mysql-slow.log
run-parts: /etc/cron.daily/logrotate exited with return code 1

Busqué en internet y todos los sitios mencionaban que la causa era que el password de la cuenta debian-sys-maint no era el que estaba indicado en el archivo /etc/mysql/debian.cnf (en Ubuntu):

[client]
host     = localhost
user     = debian-sys-maint
password = xxxxxxxxxxxxxxxx
socket   = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
user     = debian-sys-maint
password = xxxxxxxxxxxxxxxx
socket   = /var/run/mysqld/mysqld.sock
basedir  = /usr

Cambié el password en la base de datos, pero nada. Todo seguía igual. Y al revisar el hash antes y después de cambiar el password era exactamente el mismo, lo que quería decir que el password estaba bien.

Usando ping en mysqladmin

mysqladmin --defaults-file=/etc/mysql/debian.cnf ping

me di cuenta de que no se podía se conectar por problemas del socket. Entonces entendí qué estaba pasando: el directorio en donde el socket de MySQL se crea está especificado en my.cnf, y lo tengo definido como /tmp/mysqld.sock . Le puse ese valor al archivo arriba mencionado, volví a correr el proceso y todo funcionó a la perfección.

Lo anterior pasó porque primero instalé MySQL “a pie”, y recuerdo que cambié varias configuraciones; después, tuve que instalar MySQL usando apt y usé el mismo archivo de configuración. Eso fue lo que causó el problema.

¿Por qué instalé con apt si ya tenía todo configurado bien a mano? Porque lo que instalé por mi cuenta fue para hacer correr un sistema que tenía configuraciones y versiones del año del caldo, y para poder reproducir el comportamiento original tenía que tener exactamente la misma configuración. Afortunadamente eso ya quedó en el pasado y no lo necesito más.

Sobreviviendo en Windows

Llevo semana y media en el nuevo trabajo, y lo que más me “duele” es que tengo que usar Windows 7 voluntariamente a fuerzas…

Dejando atrás el hecho de que muchos de los sistemas internos funcionan solamente con la fantabulosa combinación Windows + IE (del 7 para arriba) *pausa para que se les quiten las náuseas*… el hecho de tener que hacer reportes en Excel ya se me hace de lo más normal (sí, me siento sucio).

Hecho el respectivo rant…

He estado buscando la forma de dejar Windows lo más parecido posible a XMonad. Realmente los tiling window manager me hacen la vida más fácil, y al mismo tiempo me hacen más productivo porque no se pierde tiempo acomodando ventanas o buscándolas con el mouse. Total que después de navegar un rato, lo más cercano a XMonad a lo que he podido llegar es:

  1. mDesktop. Para crear los escritorios virtuales. Usa Alt como la tecla especial y se pueden crear hasta 10 escritorios.
  2. WinSplit Revolution. Para acomodar las ventanas en ciertas regiones de la pantalla. No es para nada tan funcional como XMonad, pero peor es nada. Tampoco se puede configurar mucho que digamos.
  3. Launchy. El launcher, para reemplazar a dmenu. De los 3 programas aquí mencionados es con el que más satisfecho estoy.

Sé que lo anterior no es remotamente nada similar a dwm o XMonad, pero algo es algo. Sigo todavía buscando opciones, sobre todo en lo que al acomodo de ventanas se refiere. Si alguien tiene sugerencias, son todas bien recibidas.

Para cliente de Twitter, he estado jugando con MetroTwit, y la verdad es que es muy recomendable. Linux carece de buenos programas en este rubro (yo uso Hotot). Sin embargo, hoy me recomendaron Janetter y también me gustó la interface. Es cuestión de decidirme por alguno. Pero aun así, estoy buscando uno que deje “tuitear” desde el system tray o un popup ahí cercano, porque eso de tener que abrir la ventana para mandar un tweet es una acción que prefiero evitar en el trabajo, y no es porque me regañen por estar en Twitter (no lo hacen. No está prohibido).

En lo que a navegadores se refiere, además del fatídico IE9 *pausa para que les quiten las náuseas*… ya instalé Firefox, Chrome y Opera, siendo este último el que estoy usando como “navegador personal”, mientras que los otros los tengo para pruebas. Tenía rato que no usaba Opera “seriamente”, y me dio gusto encontrar un navegador maduro con varias opciones interesantes. Si sólo Midori tuviera soporte para más tecnologías (entre ellas Flash), no dudaría en instalarlo (y sólo por el nombre, jeje).

Entre otras cosas que instalé:

  • WinScp
  • Virtual Clone Drive (para no extrañar el mount de ISO de Linux).
  • Notepad++
  • Haskell Platform
  • Leksah
  • Imgburn

Se aceptan tips de buenos programas para… dejen agarro aire… windows… que hagan más amena la experiencia.

Obteniendo todas las posibles “palabras” de 7 letras (o menos)

Últimamente, el juego al que más le dedico tiempo (además de Tekken) es a Angry Words (apalabrados en español). Con eso que me gusta Scrabble desde hace mucho, me relaja mientras voy en el tren y al mismo tiempo me ayuda a practicar mi vocabulario.

De la misma manera, le he estado dedicando tiempo a aprender Haskell, ya que veo que algunas cosas de PLN podrían ser implementadas más fácilmente con programación funcional.

Buscaba un problema que me ayudara a practicar Haskell, a dar mis primeros pinitos en el lenguaje. Y mientras disfrutaba el mencionado juego y veía que es más de “ponle lo que sea a ver si pega” en vez de “piensa en alguna palabra interesante”, se me ocurrió crear un programa que, dada una serie de letras, mostrara todas la combinaciones posibles entre ellas. Lo veía fácil y factible, por lo que me decidí a poner manos a la obra.

¿Qué tan difícil puede ser?… me pregunté. Y aunque no es algo tan complicado, sí me tomó más tiempo del que pensaba debido a que había que hacer el cambio a programación funcional y no a imperativa.

Primero, a definir el algoritmo:

Tomemos una palabra de 3 letras (por conveniencia, más adelante verán por qué), digamos “ola”. ¿Qué es lo que quiero obtener? La lista de posibles permutaciones con esas 3 letras, es decir: ola, oal, loa, lao, aol, alo. Aquí me di cuenta de un patrón: tomo una letra de la palabra, la pongo al principio, y simplemente tomo las otras 2 letras restantes y les cambio el orden. Para comenzar, tomo la “o” como la letra principal, entonces me quedo con “la”, y las únicas combinaciones posibles son “la” y “al”; después, agrego la letra principal “o” y la pongo al principio de cada palabra, obteniendo “ola”,”oal”. Continúo con la siguiente letra, la “l”, la tomo como principal, quedándome “oa”, de la cual obtengo “oa” y “ao”; le pongo la “l” al principio de cada una y obtengo “loa”,”lao”. Por último tomo la “a” como letra principal, lo que me deja con “ol” como el resto, obteniendo “ol” y “lo”; le pongo la “a” al principio de cada una y resultan “aol”, “alo”. Juntando todos los resultados parciales, obtengo la lista de palabras que estoy buscando.

Con la definición anterior, recursivamente se pueden analizar palabras de cualquier longitud. ¿Buenas noticias para los que juegan apalabrados? En teoría, si es que tienen la paciencia de ver todos los resultados. ¿Cuántos son? Saquemos cuentas:

Una palabra de 3 letras resultó en una lista de 6 palabras. ¿Cuántas resultarán de una de 4? Como lo que buscamos son permutaciones, la fórmula es sencilla:

n!

Revisemos: 3! = 3x2x1 = 6. ¡Bien! Si cuadra el resultado

Entonces, con 4 letras tendremos: 4! = 4x3x2x1 = 24 Todavía no son muchas…

Con 5 : 5! = 5x4x3x2x1 = 120 ya da flojera ver tantas permutaciones…

¿Y con 7? Pues 7! = 7x6x5x4x3x2x1 = 5040 Está bien que no haya límite de tiempo en cada jugada de apalabrados, pero qué flojera (o ganas de ganar) de aquél(la) que se ponga a leerla cada vez.

¡Ajá! Dirán ustedes: ¿qué pasa si hay letras repetidas? Obviamente habrá palabras repetidas también, lo cual reduce nuestra lista. ¿A cuánto? Oh benditas matemáticas:

n!/(a!b!c!…)

En donde a es el número de veces que se repite una letra, b es el número de veces que se repite otra, c es el número de veces que se repite otra… y así sucesivamente.

Supongamos que tenemos las letras “atajada” (si las tienen, ¡no la piensen y jueguen esa palabra!). La letra “a” se repite 4 veces, entonces, tendremos:

7!/4! = 7x6x5 = 210

Quizá pude haber pensado el algoritmo con una palabra de 4 letras desde el principio, y aunque sí revisé a mano después, me era más fácil iniciar con una de 3 (sólo 6 posibles permutaciones).

Luego, a hacer el programa. El resultado, a sabiendas de que puede haber una mucho mejor implementación, es una belleza de 18 líneas de código (y porque puse doble enter en algunos lugares):

Continue reading Obteniendo todas las posibles “palabras” de 7 letras (o menos)

XMonad: Cambiar el nombre del layout que se muestra

Hace tiempo escribí sobre XMonad y un xmonad.hs básico en donde mostraba cómo mostrar íconos en vez del título del layout. Esta vez esalgo similar, pero como ahora sí estoy estudiando Haskell en forma, ando buscando cómo hacer lo que quiero con guards:

En uno de los escritorios estoy usando LayoutCombinators para combinar 2 layouts (concretamente simpledTabbed y DragPane Horizontal). Al mostrarse el nombre del layout aparece lo siguiente:

“combining Tabbed Simplest with DragPane Horizontal 0.1 0.099999999”

Debido a su longitud, me quita espacio del título de la ventana activa, por lo que pensé hacer un shorten, pero después recordé que en la laptop hago pattern matching para mostrar un ícono en vez del nombre del layout, por lo que pensé hacer algo parecido: si el nombre del layout comienza con “combining”, muestro un nombre que yo defina, y en cualquier otro caso muestro el nombre original.

El layout quedó así:

myXmobarPP h = xmobarPP
             { ppOutput = hPutStrLn h
             , ppCurrent = xmobarColor "green" "" 
             , ppHidden = xmobarColor "#5f7962" ""
             , ppVisible = xmobarColor "#f4a460" ""
             , ppUrgent = xmobarColor "#cc0000" "" . wrap "*" "*"
             , ppSep = " | "
             , ppWsSep = "  "
             , ppLayout = xmobarColor "#5CBAF5" "" .
                          (\lName -> showLayoutName lName)
             , ppTitle = xmobarColor "white" "" . shorten 150
             }

showLayoutName :: String -> String  
showLayoutName a | Just rest <- stripPrefix "combining" a = "Tabbed + DragPane H" 
showLayoutName a = a

Donde lo que quiero hacer está en ppLayout: una expresión lambda para revisar si el título comienza con “combining” o no. Esa revisión la hago en la función showLayoutName con la función stripPrefix, que recibe una lista y regresa otra lista que contiene los elementos después del prefijo indicado si es que existe, o Nothing en caso contrario. Si el título del Layout comienza con “combining”, regreso “Tabbed + DragPane H”, y si no, simplemente regreso lo que me llegó.

Intenté hacerlo con guards, pero nomás no me compiló el código, y como estoy en el trabajo, no me dio más tiempo de probar, por eso lo implementé como aquí se muestra.

Si quisiera hacerlo en Scala, el código quedaría así:

val xmobarColor = (bgColor: String) => (fgColor: String) => (output: String) => {
  // Hacer algo con los parámetros y regresar un String
  ...
}

val showLayoutName = (layout: String) => {
  layout.startsWith("combining") match {
    case true => "Tabbed + DragPane H"
    case _ => layout
}

// Asignando todo a ppLayout

val ppLayout = ((xmobarColor("#5CBAF5")("")) compose showLayoutName)

// Siendo layoutName el nombre del layout actual

ppLayout(layout)

Aunque sigo siendo novato en Scala (y para esos fines, en programación funcional), me late más la forma concisa de Haskell. Hacer function composition en scala es agregar demasiadas palabras (aunque si usara scalaz todo cambiaría), mientras que en Haskell el currying, la aplicación parcial y la composición se hacen sin mayor complicación.

Sigo estudiando y practicando.

De “hackeos” y otras cosas

Muchos de ustedes se dieron cuenta que a principios de esta semana el blog fue bloqueado por Google debido a que se detectó malware en él. Aunque no fue la primera vez que me ponen anuncios o redirecciones a sitios que venden viagra o pornografía, sí fue la primera vez que sufrí el bloqueo de la gran G.

La situación parece haber vuelto a la normalidad, pero me lo tomo con pincitas, porque ya antes habíamos (incluyo al panda, quien me ha hecho grandes favores en este blog y hosting en general) hecho limpieza y en teoría todo estaba bien, y zas… nos cayó por donde menos esperábamos.

Razones puede haber muchas, pero las principales parece que ya han sido solucionadas: borrar los lugares que no uso o no actualizo tan seguido, así como sus bases de datos. En concreto:

  • Desaparece el blog de tecnología. No porque quiera, sino porque no tengo tiempo de estarle dando mantenimiento. Todos los posts de allá ya habían sido migrados aquí desde hace varios meses.
  • Desaparece el sitio de las fotos. Quizá muchos no lo conocieron porque nunca hubo una liga directa en el blog. Era Gallery 3, pero la última vez que le di mantenimiento fue en la versión 3.02 RC. También se va por falta de tiempo.
  • Borré varios sitios y bases de datos que alguna vez ofrecí a gente o instituciones que lo necesitaban pero que a fin de cuentas nunca usaron. Ni modo, uno les da la oportunidad, pero a final de cuentas depende de ellos .

Sinceramente, para mí no hay nada mejor que tener el control total de lo que uno usa. Por eso la instalación de WordPress de este blog se hizo desde ceros y la mantengo a mano en vez de usar la versión que se ofrece en el hosting. Sin embargo, la falta de tiempo es una situación que me afecta mucho en estos momentos, por lo que, para mi desgracia, no puedo mantener tantos sitios al mismo tiempo. Las fotos es lo que quizá más me duele, pero no hay de otra por el momento. Las subiré ya sea a Picassa o a Flickr (aunque me inclino más por el primero) en una oportunidad que tenga.

Por lo demás, parece que todo está en orden. Quisiera darle una manota de gato al blog (me prometieron un skin personalizado para el blog hace como 2 años), pero sinceramente con todo lo que traigo entre manos (una gran parte es el esclavajo) todo tendrá que esperar.

Ahí les encargo si ven algo raro en el blog, o si les vuelven a salir mensajes o anuncios de productos milagrosos o redirecciones a sitios extraños.

Errores

Como ya se habrán dado cuenta, he andado muy desconectado del blog, y para el caso también de internet. Han sido semanas pesadas en el trabajo, pero la anterior se caracterizó por una carga de trabajo moderada con una de presión bastante más grande.

Para no hacer el cuento largo, me pidieron hacer una prueba de estrés en un servidor. Pensé que la prueba en sí sería fácil (con algo como ab), pero leyendo y siguiendo el consejo del buen panda, opté por usar siege, herramienta que también es mencionada en el libro de Tomcat de O’Reilly. Leí, según yo me preparé bien, revisé varias veces las condiciones de la prueba, y en el día y la hora indicada la realicé (en realidad fueron varias).

Pensé que todo había salido bien, así que procedí a hacer el respectivo reporte… y fue donde realmente comenzó todo. Dejemos al lado que el formato del reporte no fue el que esperaban: los resultados no cuadraban. Y entre que yo soy un noob para esto de las pruebas y entre que no confiaban en que hubiera realizado la prueba correctamente, fueron 3 días para olvidar, pues terminé saliendo en promedio después de las 12 de la noche.

Entrando en detalles más técnicos, siege pide un archivo con una lista de URL a probar. El problema, y mi error, fue haber puesto URL de más, por haber entendido que se probarían N tipos de páginas y no N páginas exactamente. Pero por lo demás, las características de la prueba no estaban mal, y la forma de ejecutar la prueba tampoco. ¿Entonces?

Lo que me alegaban era que en la prueba se emulaban N número de usuarios que accederían al servidor al mismo tiempo, pero los resultados reportaban que no era así, y el número de veces que se visitaban los URL era realmente muy poco para el tiempo que duró la prueba. El panda me auxilió muchísimo con la interpretación de los resultados, y efectivamente, salió a relucir que una de las razones era por haber puesto URL de más. Error 100% mío, y en una situación laboral como la que estoy viviendo ahora, era de esperarse que me fueran a reclamar, con justa razón. Sin embargo, aun con reconocer mi error, los resultados marcaban claramente que el servidor no aguantaba mucho, pero me seguían insistiendo que la forma de hacer la prueba había estado mal, independientemente del número de páginas que había seleccionado para probar.

Después de la tormenta, se corrió una prueba emergente para comprobar que realmente había hecho la prueba original correctamente. Los resultados no mentían: se probaron menos páginas (un número cercano a las que originalmente se tenía planeado), pero se mostraba también la tendencia del servidor a no aguantar al número de usuarios indicados al mismo tiempo.

¿Qué aprendí de todo esto?

  1. Que el mundo del benchmark es mucho, pero mucho más complicado de lo que yo creía.
  2. Que aunque sé que soy humano y que obviamente me puedo equivocar, un error bajo esta situación puede costarme muy caro.
  3. Que estoy bajo mucha más presión que la que originalmente  pensaba.
  4. Que no quiero estar por siempre en una situación laboral como la actual.

Ahondando un poco en el punto 4, no tiene mucho que ver lo pesado del trabajo, o ni siquiera que no paguen las horas extra; tiene mucho más peso para mí el tiempo que le puedo dedicar a los demás, y por supuesto, a mí mismo.

Añoraba el fin de semana. Lástima que ya terminó. Tengo en puerta decisiones muy grandes, y relativamente poco tiempo para hacerlas. Como hace algunos años, necesito que los días tengan al menos 48 horas para poder hacer todo lo que debo. Mientras tanto, aquí andamos, tratando de no sucumbir ante la situación.

Agradezco muchísimo al panda por su invaluable ayuda y su tiempo en estos días, así como las palabras de aliento de varios de los mexicanos en Japón (ellos saben quienes son).

Transición a Android

Después de haber usado teléfonos celulares dirigidos al mercado japonés, hace un par de semanas me decidí a comprar un smartphone de “la nueva generación”. Y como ustedes, quienes me hacen el favor de leerme, seguramente están imaginando, mi opción fue un teléfono con Android.

Antes que nada, he de hacer mención que no es mi primer smartphone. Hace algunos años usé uno estilo “blackberry”, el cual tenía el infame windows mobile 6, pero lo cambié en la primera oportunidad que tuve debido a que en ese entonces el mercado japonés todavía no estaba preparado para esa clase de teléfonos.

Primero fue muy difícil decidirme por un modelo en particular. Tener Android sólo significa una cosa para mí: rootearlo, es decir, alterarlo para tener acceso como súper usuario, lo que significa tener el control absoluto del teléfono. Si hubiera escogido un iPhone también le habría hecho jailbreak. El caso es que había que escoger un teléfono que se pudiera rootear, pero los de fabricantes japoneses se han destacado por no poder hacerlo. Y por otro lado, con un smartphone perdería todas las funciones que han caracterizado a los teléfonos celulares nipones desde hace muchos años: dinero electrónico, televisión, acceso a la red WAP (que es muy usada en este país). Por fortuna, la nueva generación de smartphones con Android contiene también esas funciones, pero siendo de fabricantes japoneses significa no poder rootearlo. Tenía que decidir entre el root o la conveniencia de las funciones arriba mencionadas.

Durante unos días pensé cuál podría ser mi mejor opción, y me decidí al principio por un Aquos Phone de Softbank, que viene con Gingerbread (Android 2.3) y las funciones de los teléfonos japoneses. Sacrificaría el root por ellas.

El hecho de que este teléfono tome fotos en 3D sinceramente me daba lo mismo.

Estuve indeciso, pero aun así fui a una tienda de Softbank a hacer cambio de teléfono, y me dijeron que era mejor que esperara hasta el 1 de julio, ya que el pago del teléfono anterior terminaba en junio y así no sufriría ningún cargo extra por “deshacerme” del teléfono antes de tiempo (por sus contratos raros que te obligan a usar un equipo por mínimo 2 años). Yo iba medio convencido por el teléfono mostrado arriba, pero tener que esperar varios días me dio tiempo para estudiar otras posibilidades.

Consultando en Twitter, Felipe me recomendó un teléfono: el HTC Desire HD. Erick hizo hincapié en lo que ya venía pensando: ¿sacrificaría el root por funciones japonesas? El punto era que yo sí usaba esas funciones, en especial el dinero electrónico y la red WAP, por lo que sí me dolería dejarlas… pero ustedes saben que puede más el lado geek, y después de ver lo que ofrecía el teléfono recomendado, aunado con que los HTC son los teléfonos que tienen de las mejores redes de desarrolladores (y por ende, altas probabilidades de poder ser rooteados), me convencieron y me di a la tarea de buscarlo. Softbank lo maneja como el modelo 001 HT, y al revisar el sitio web, me enteré de que salió a la venta en Japón en diciembre del año pasado. Siendo un teléfono ya no tan nuevo, creí que sería fácil encontrarlo…

Continue reading Transición a Android

Plugin de Veetle 64 bits

Muy de vez en cuando quiero ver un video o transmisión en vivo que necesita el plugin de veetle, pero el download que viene por default en la página de descargas es para arquitecturas de 32 bits. Intenté instalarlo con ndiswrapper, pero aun así no funcionaba.

Buscando en internet, me encontré que veetle también tiene plugin para arquitecturas de 64 bits, pero no está fácil encontrarlo. Por acá la liga:

http://veetle.com/download.php/veetle-0.9.17plus-linux-install.sh

Instálenlo como usuario normal. Lo que hace es copiar los plugins necesarios al directorio ~/.mozilla/plugins

Listo. VeetleTV funcionando en 64 bits. Rara vez lo uso, pero nunca está de más tenerlo.

Cabe mencionar que vlc también puede reproducir y grabar streams de Veetle. Hay muchos tutoriales en internet, por ejemplo:

http://netimports.blogspot.com/2010/10/how-to-record-watch-veetle-broadcasts.html

Queda para el registro 🙂