sábado, 31 de julio de 2010

Barajitas premiadas (#13) - MySQL Sandbox

Esta herramienta me parece una excelente alternativa para hacer pruebas con MySQL. Les cuento para qué la utilicé para que se hagan una idea de su utilidad.

Por cuestiones de trabajo necesitaba hacer pruebas con varias bases de datos MySQL, esto porque tenemos un entorno con replicación maestro-esclavo bien diverso.

Primero pensé en montar varias máquinas virtuales en mi computador -con Ubuntu- pero éste tiene serias limitaciones de memoria y procesamiento, por lo que descarté VMWare y VirtualBox. Luego pensé en instalar una máquina virtual más liviana que compartiera funcionalidades del kernel, algo tipo Zonas de Solaris, conseguí Linux-VServer pero lo encontré bastante limitante, tuve que recurrir a un montón de artilugios con IPTables para lograr que medio funcionara.

Entonces... Pensé en instalar varias instancias de la base de datos en mi máquina... Cuando comencé a configurar cada una comenzó el karma, por lo engorroso de sus archivos de configuración. Y de repente, se hizo la luz! Conseguí el MySQL Sandbox y listo!

Esta herramienta permite configurar tantas instancias de MySQL como se desee a partir de sus binarios. Por ejemplo:

$ make_sandbox mysql.tar.gz
$ ~/sandbox/MY_SANDBOX/start_all
$ mysql -u root --password=msandbox -h localhost --port=17050 &
$ mysql -u root --password=msandbox -h localhost --port=17051 &
$ mysql -u root --password=msandbox -h localhost --port=17051 &

Enjoy! Siempre puede ver los archivos de configuración de cada instancia (my.cnf) dentro de las carpetas correspondientes a cada nodo, dentro del sandbox.


PHP Auto Conf

Perdonen que he andado un poco perdido con el blog, he estado full con el desarrollo de una herramienta para automatizar tareas utilizando scripts escritos en PHP, la he llamado phpautoconf.

Pretendo que facilite la automatización de tareas, sobre todo para sysadmins. Espero escribirles pronto al respecto, de momento comenzaré a colocar todo en GitHub; ya les avisaré!

jueves, 29 de julio de 2010

Cómo hacer que un script se ejecute al iniciar/reiniciar/apagar el sistema

Este artículo me parece que explica de forma sucinta y excelente cómo hacer que un script se ejecute al iniciar/reiniciar/apagar el sistema. Además, siguiendo el método mencionado dejaremos un script en init.d que podría ser utilizado durante una sesión para iniciar o detener el servicio.

Making scripts run at boot time with Debian

lunes, 26 de julio de 2010

Barajitas premiadas (#12) - tail

Del artículo Chat p2p Netcat cifrado con OpenSSL espero sacar varias barajitas...

La primera, tiene que ver con el comando tail. Este comando permite ver las últimas líneas de un archivo. Por ejemplo, a continuación se mostrarán las últimas 20 líneas del archivo de logs del sistema; muy útil para obtener información cuando se adjunta algún equipo al computador (ver también dmesg).

# tail -20 /var/log/messages

Ahora, este comando posee una opción poderosa que permite ver el contenido de un archivo en línea, de forma sigilosa (opción -f), es decir, conforme este cambie se irán mostrando sus registros... Esto es súper útil para chequear logs del sistema (Ej. logs de un servidor HTTP).

#  tail -f /var/log/apache2/error.log

Y para finalizar el artículo, hay veces en las que deseo realizar una tarea para cada nuevo registro escuchado por el tail, para ello puedo utilizar el comando read dentro de un bucle de la siguiente forma:

#  tail -f /var/log/apache2/error.log | while read -r line; do php procesador.php $line; done

El comando mostrado arriba ejecutará el script procesador.php para cada nueva línea dentro del archivo /var/log/apache2/error.log. Podríamos suponer que el script se conecta a una BD y deja el nuevo registro en ella.


domingo, 25 de julio de 2010

Chat p2p Netcat cifrado con OpenSSL

Este artículo lo escribí pensando en incluir un canal cifrado para el chat p2p que comenté días atrás en: La navaja suiza.

Quería incluir un cifrado sencillo simétrico (utilizando DES) con OpenSSL y además quería hacerlo para cada entrada enviada entre Cliente y Servidor y no por todo un bloque.

Como me gustó tanto este ejercicio, creé los siguientes scripts (que de preferencia recomiendo ejecutar en el orden en que son presentados):
  1. start_server.sh Inicia el netcat como escucha y envía la salida a un archivo (OUTPUT_FILE). Podrá notar que siempre que se corre este script, es vaciado el contenido del OUTPUT_FILE
  2. start_client.sh Comienza la lectura sigilosa de un archivo (de tipo PIPE*) utilizando el comando tail -f. Cada nueva entrada en este archivo (INPUT_FILE) será enviada al servidor haciendo uso de netcat.
  3. receiver.sh Este script y el mencionado seguidamente, son los encargados de tomar las entradas o salidas de netcat y cifrarlas o descifrarlas. En este caso, este script toma lo que ha recibido el servidor (OUTPUT_FILE) y lo descifra (puesto que dentro del mismo quedará el contenido cifrado)
  4. send.sh Este script permite enviar un mensaje desde el cliente al servidor, para lo cual utiliza el archivo INPUT_FILE, donde coloca el mensaje cifrado.

*: En el siguiente enlace podrá conseguir información bastante útil acerca de archivos FIFO.

En definitiva, los scripts start_server.sh y start_client.sh establecen la conexión TCP a través de netcat. Luego, los scripts send.sh y receiver.sh cifran y descifran los mensajes que viajarán entre cliente y servidor. Para utilizar estos scripts correctamente, deberá tener en el cliente los archivos start_client.sh y send.sh, y en el servidor, los archivos start_server.sh y receiver.sh.

Los scripts:

Script: start_server.sh
#!/bin/bash
OUTPUT_FILE='output'
PORT='1234'

if [ $# -eq 2 ]
then
        OUTPUT_FILE=$1
        PORT=$2
elif [ $# -gt 0 ]
then
        echo "Usage: start_server.sh [output_file port]"
        exit
fi

cat /dev/null > $OUTPUT_FILE && netcat -l -p $PORT > $OUTPUT_FILE

Script: start_client.sh.
#!/bin/bash
SERVER='localhost'
PORT='1234'
INPUT_FILE='input'

if [ $# -gt 3 ]
then
        echo "Usage: start_client.sh [server] [port] [input_file]"
        exit
else
        if [ $1 ]; then SERVER=$1; fi
        if [ $2 ]; then PORT=$2; fi
        if [ $3 ]; then INPUT_FILE=$3; fi
fi

if [ -p $INPUT_FILE ]
then
        tail -f $INPUT_FILE | netcat $SERVER $PORT
else
        echo "$INPUT_FILE isn't a pipe file. First, you may want to run: mkfifo $INPUT_FILE"
fi

Script: receiver.sh
#!/bin/bash
PASSWORD='1234'
OUTPUT_FILE='output'

if [ $# -gt 2 ]
then
        echo "Usage: receiver.sh [output_file] [password]"
        exit
else
        if [ $1 ]; then PASSWORD=$1; fi
        if [ $2 ]; then OUTPUT_FILE=$2; fi
fi

tail -f $OUTPUT_FILE | \
        while read -r line
        do
                echo $line | openssl enc -d -a -des3 -pass pass:$PASSWORD
        done

Script: send.sh
#!/bin/bash
PASSWORD='1234'
INPUT_FILE='input'

if [ $# -lt 1 ] || [ $# -gt 3 ]
then
        echo "Usage: send.sh message [password] [input_file]"
        exit
else
        if [ "$1" ]; then MESSAGE=$1; fi
        if [ $2 ]; then PASSWORD=$2; fi
        if [ $3 ]; then INPUT_FILE=$3; fi
fi

if [ -p $INPUT_FILE ]
then
        echo $MESSAGE | openssl enc -e -a -salt -des3 -pass pass:$PASSWORD -out $INPUT_FILE
else
        echo "$INPUT_FILE isn't a pipe file. Probably you don't have a server_client running"
fi

Un ejemplo:

En una consola (Consola #1 - Servidor):
$ ./start_server.sh &
$ ./receiver.sh

En otra consola (Consola #2 - Cliente):
$ mkfifo input
$ ./start_client.sh &
$ ./send.sh "primer envío"



viernes, 23 de julio de 2010

Barajita premiada (#11) - ejecutar un comando para cada línea de un archivo

Típico que tenemos en algún archivo un listado de nombres y queremos ejecutar un comando para cada una de las líneas del mismo. Por ejemplo: supongamos que tengo un directorio con un montón de archivos, pero quiero borrar sólo un subconjunto de los contenidos en éste. Entonces, podría copiar los nombres (uno por línea) dentro de un archivo y pedir que se ejecute el comando rm por cada línea... Esto no tiene sentido si el subconjunto está compuesto por 5 nombres o menos, pero si son más, seguro que sería de utilidad algo como:

$ for i in `seq 1 100`; do touch $i; done # generando archivos vacios
$ cat a_borrar # mostrando el archivo que contiene la lista de elementos a borrar
22
3
4
65
6
12
45
90
32
76
48
98
32
$ for i in `cat a_borrar`; do rm $i; done # borrando los archivos especificados



miércoles, 21 de julio de 2010

Barajitas premiadas (#10) - countries, states, cities

No puedo dejar pasar esta barajita porque precisamente estaba buscando al respecto y conseguí unos excelentes enlaces, y antes de que se me olvide...

Típico de un sistema... dos o tres combos dependientes uno del otro donde se cargarán paises, estados y ciudades (Ej. Fulano vive en Venezuela->Miranda->San Antonio de Los Altos) ¿el problema? los datos...

De dónde saco los datos más actualizados, pues por supuesto que ya mucha gente tuvo el mismo problema. Aquí les dejo los dos vínculos que encontré mejor, el primero el oficial y el segundo (extra-oficial) sencillo, pero con estados sólo de EEUU:


Están en inglés, pero a final de cuentas si queremos algo internacionalizable (el común hoy día), guste o no, esa es la segunda lengua por excelencia.