viernes, 11 de marzo de 2011

Barajita premiada (#22) - copiando en consola con barra de progreso

Copiar ficheros de un lado a otro por consola resulta trivial, esto se puede hacer utilizando el comando cp. Luego, hay momentos en los que se debe copiar mucha información... Por ejemplo, yo hago respaldos de mi info en un disco externo cada cierto tiempo y son varios gigas, entonces al hacer una copia no conocía nada del estatus de la copia, sólo me quedaba la persignación... XD

Podría pensar que soy un freak por hacer copias por consola, la cuestión es que es mucho más útil porque puedo manipular la salida de error estándar y no dejo colgada la interfaz gráfica!

Generalmente hacía algo como:

# cp -r /etc/ /home/ /opt/ /root/ /var/ 201111_respaldo_linux 2>201111_respaldo_linux/errores

Ahora, sólo sabía como iba esto cuando terminaba... Como máximo podía ir viendo errores con un "tail -f" sobre el fichero de errores, algo así:

# cp -r /etc/ /home/ /opt/ /root/ /var/ 201111_respaldo_linux 2>201111_respaldo_linux/errores & tail -f 201111_respaldo_linux/errores

Pero ya no sufro más!!! Encontré una mejor manera de hacer esto, utilizando rsync que me da detalle del progreso de la operación...

# rsync -aRv --progress --delete /etc/ /home/ /opt/ /root/ /var/ 201111_respaldo_linux 2>201111_respaldo_linux/errores

Esto mostrará el estatus de la copia (al más puro estilo scp), las opciones: -a, -R, -v, --progress y --delete, las utilizo -respectivamente- para: copiar ficheros, utilizar nombres relativos, activar modo verboso, mostrar progreso y eliminar contenidos diferentes de la fuente en el destino.


lunes, 28 de febrero de 2011

Optimizando tablas InnoDB en MySQL

Cuando utilizamos MySQL es común optimizar tablas con muchos registros con cierta periodicidad, esto para solventar problemas de fragmentación, entre otros. La verdad esta es una de las cosas del modelo de PostgreSQL que echo en falta, quizás no es tan "amigable" pero todo queda claro desde el inicio.

En PostgreSQL hay un proceso de aspiradora (vacuum) que va eliminando periódicamente registros inutilizados en tablas, su configuración, pan nuestro de cada día para un admin de BBDD que debe ajustarlo con frecuencia.

Bueno.... Volviendo a MySQL, si necesita optimizar tablas InnoDB, lo mejor que puede utilizar son ALTER nulos, estas son instrucciones DDL de tipo ALTER sin parámetros que permiten seguir trabajando con las BBDD, porque realiza copias temporales en disco. La cuestión es que esta herramienta "reconstruye" la tabla y elimina, entre otros, los problemas de fragmentación.

Aquí les dejo un script para optimizar de "un sólo golpe" varias tablas InnoDB:

#!/bin/bash

if [ $# -lt 2 ]; then
        echo "You must specify database host"
        echo "Eg. script.sh MY_DATABSE 192.168.10.1"
        exit
fi

db="$1"
host="$2"
user="root"
declare -a tables=(Table1 Table2 Table3)

stty -echo
read -p "Enter MySQL's Admin password: " password
stty echo

for table in ${tables[@]}; do
        echo $table &&
        time mysql -u $user --password=$password -h $host $db -e "ALTER TABLE $table ENGINE=INNODB"
done

Básicamente optimizamos las tablas especificadas (en un arreglo) e imprimimos el tiempo que toma cada instrucción (time).

Si tiene la certeza de que todas las tablas de una BD son InnoDB y quiere optimizarlas todas aún más rápido, puede hacerlo valiéndose del comando "show tables"...

#!/bin/bash

if [ $# -lt 2 ]; then
        echo "You must specify database host"
        echo "Eg. script.sh MY_DATABSE 192.168.10.1"
        exit
fi

db="$1"
host="$2"
user="root"

stty -echo
read -p "Enter MySQL's Admin password: " password
stty echo

mysql -u $user --password=$password -h $host --batch --skip-column-names $db -e "SHOW TABLES" |
while read table; do
        echo $table &&
        time mysql -u $user --password=$password -h $host $db -e "ALTER TABLE $table ENGINE=INNODB"
done

La única diferencia es que las tablas ya no son especificadas a través de un arreglo (que recomiendo para BBDD grandes, donde optimizar todas las tablas podría demorar toda la vida), sino que se toman directamente del comando "SHOW TABLES" para una BD especificada.


sábado, 26 de febrero de 2011

Ejecutando lotes de modificaciones (INSERT, UPDATE, DELETE) en BBDD

Esta me salvó hace poco de un proceso de modificaciones (INSERT, UPDATE y DELETE) eterno!

Si necesita realizar muchas operaciones de las comentadas, por ejemplo un par de millones, resulta bastante útil y reduce considerablemente el tiempo de respuesta, incluir BEGIN y COMMIT al comienzo y final del lote.

Con esto eliminamos sobrecarga realizando una sola transacción y no una por instrucción. Espero sea de utilidad... Recuerde: BEGIN; INSERT...; COMMIT;

Barajita premiada (#21) - número de días en un mes

Esta es una barajita breve, pero no por ello menos útil. Se trata de un método sencillo en *nix de obtener el número de días que tiene un mes:

$ month=02; year=2011
$ cal $month $year | xargs | awk '{print $NF}'
28

Obtengo los días en formato calendario, los paso por xargs para quitar retornos de carro/tabulaciones y luego pido el último elemento con AWK.


miércoles, 19 de enero de 2011

Instalando dos versiones de PHP-CLI en una misma máquina

El otro día tuvimos problemas instalando dos versiones del interprete de línea de comandos de PHP (PHP-CLI) en una misma máquina, específicamente, queríamos instalar en una máquina con Ubuntu 10.04 que ya tenía PHP5.2, PHP5.3.

Mi primo Daniel (http://dcestari.posterous.com/), quien es un crack como dicen por estos lares (en Venezuela diríamos un duro), dió con la solución...

Descargó el fichero con los fuentes de php.net y configuró utilizando las opciones que trae el .deb que descargas desde los repos. A continuación las opciones:

# ./configure --prefix=/usr/local/ --disable-cgi \
--program-suffix=5.3 \
--with-config-file-path=/etc/php5.3/cli \
--with-config-file-scan-dir=/etc/php5.3/cli/conf.d \
--build=$(dpkg-architecture -qDEB_HOST_GNU_TYPE) \
--host=$(dpkg-architecture -qDEB_HOST_GNU_TYPE) \
--sysconfdir=/etc \
--localstatedir=/var \
--disable-debug \
--with-regex=php \
--disable-rpath \
--disable-static \
--with-pic \
--with-layout=GNU \
--enable-calendar \
--enable-sysvsem \
--enable-sysvshm \
--enable-sysvmsg \
--enable-bcmath \
--with-bz2 \
--enable-ctype \
--with-db4 \
--without-gdbm \
--with-iconv \
--enable-exif \
--enable-ftp \
--with-gettext \
--enable-mbstring \
--with-pcre-regex=/usr \
--enable-shmop \
--enable-sockets \
--enable-wddx \
--with-libxml-dir=/usr \
--with-zlib \
--with-kerberos=/usr \
--with-openssl=/usr \
--enable-soap \
--enable-zip \
--with-mhash=yes \
--with-libedit \
--without-mm \
--enable-pdo \
--with-pdo-mysql \
--with-mysql --without-sybase-ct --with-sqlite \
--without-mssql --with-sqlite3 --enable-pcntl \
--without-pear

Luego, compilamos con make y lo novedoso.... en lugar de instalar el compilado con el típico make install, el descubrimiento del año (al menos para mi), utilizamos checkinstall lo que genera un .deb -con el nombre especificado- que después se puede instalar y desinstalar fácilmente con dpkg.


lunes, 10 de enero de 2011

Copiando permisos de una BD MySQL a otra

Este script lo encontré en la red y me pareció que debía publicarlo aquí por su gran utilidad:
#!/bin/bash
# adapted from (http://www.pyrosoft.co.uk/blog/2006/10/18/show-grants-for-all-users-on-mysql/)
mysql --batch --skip-column-names -e "SELECT user, host FROM user" mysql |
while read user host; do
  echo "# $user @ $host"
  mysql --batch --skip-column-names -e"SHOW GRANTS FOR '$user'@'$host'"
done

El script mostrado arriba saca todos los usuarios de la BD y luego retorna un script con los privilegios para cada uno de estos, lo que permitiría migrar privilegios y usuarios de una BD MySQL a otra.


martes, 14 de diciembre de 2010

Barajita premiada (#20) - seq con formato

Típico que necesita sacar por consola una secuencia de números, entonces utiliza el comando seq, por ejemplo:
$ seq 1 5 
1
2
3
4
5

O necesita esos números de dos en dos:
$ seq 1 2 5
1
3
5

La cosa se pone interesante cuando requiere formatos, por ejemplo obtener siempre números de dos cifras, entonces puede utilizar:
$ seq -f "%02g" 1 5
01
02
03
04
05

A este punto usted se preguntará, ¿y para qué puede serme útil esto? Pues yo no lo sé, no mentira, esto podría resultar útil para -por ejemplo- filtrar entradas de un log de apache donde cada línea lleva algo como:
192.168.0.1 - - [01/Nov/2010:00:00:33 +0100] "GET ..." 

Si quisiera extraer cada entrada para un día específico podría utilizar un script del tipo:
#!/bin/bash

for day in `seq -f "%02g" 1 31`; do
  count=`egrep -i "\[$day/Nov/[0-9:+ ]+\] \"GET $line" logs/*access.$month.log | grep " 200 " | wc -l`
  echo "$day,$line: $count"
done

¿Y para qué sirvió el seq? para hacer un "for" con valores de dos dígitos y que así tuviera sentido el grep que hacemos dentro del búcle (ver: $day).