viernes, 16 de mayo de 2014

Class 'GearmanClient' not found & configure: error: Please install libgearman

Error: PHP Fatal error:  Class 'GearmanClient' not found

Este error de apache requiere esta instalacion:
pecl install gearman

Y esta anterior probablemente va a marcar:
 configure: error: Please install libgearman

Esto seguira saliendo como error aunque ya tengas instalado libgearman! La solucion es instalar el paquete de development como adicional:

yum install libgearman-devel

Ya con eso sigue:
pecl install gearman

Y listo. Dependiendo de tu sistema puede que necesites agregar lo siguiente en /etc/php.ini:
extension=gearman.so

Reinicia apache (service httpd restart) y listo.

jueves, 2 de mayo de 2013

Usando SPDY en Nginx y CentOS 5

Aqui los pasos seguidos para completar esta instalacion en CentOS 5.9 y Nginx 1.4.0

El modulo ya se encuentra incluido en la version 1.4.0 de Nginx por lo que solo basta agregarlo a las opciones de compilacion.

Primero hay que resolver la dependencia en openssl 1.0.1+. CentOS 5 tiene openssl 0.98 por lo que crearemos una instalacion secundaria de openssl en /usr/local/ssl:
wget http://www.openssl.org/source/openssl-1.0.1e.tar.gz 
tar zxvf openssl-1.0.1e.tar.gz 
cd openssl-1.0.1e 
./config --shared -–openssldir=/usr/local/openssl 
make
make install

Podemos ver la nueva version de openssl con el comando:
/usr/local/ssl/bin/openssl version

Con eso instalado podemos bajar la ultima version de Nginx desde http://www.nginx.org/download/ :

wget http://nginx.org/download/nginx-1.4.0.tar.gz
tar -xvzf nginx-1.4.0.tar.gz
cd nginx-1.4.0


Y agregamos opciones para utilizar nuestra segunda instalacion de openssl:
./configure --with-http_ssl_module --with-cc-opt="-I/usr/local/include -I/usr/local/ssl/include -I/usr/include" --with-ld-opt="-L/usr/local/ssl/lib -Wl,-rpath,/usr/local/ssl/lib -lssl -lcrypto -ldl -lz" --with-http_geoip_module --with-http_sub_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_spdy_module --with-debug

make
make install

Eso nos da un executable de Nginx en /usr/local/nginx/sbin/nginx

Podemos checar la version con: /usr/local/nginx/sbin/nginx -V

Ahora agregamos las opciones de SPDY a la configuracion:
vim /usr/local/nginx/conf/nginx.conf


    server {
        listen       xxx.xxx.xxx.xxx:443 ssl spdy;
        server_name  mydomain.com;


Y adicionalmente agregamos compresion en los headers:
spdy_headers_comp 7;

Despues de eso, reiniciamos el servicio y podemos checar los resultados en http://spdycheck.org/

martes, 26 de marzo de 2013

Ejecuta un comando en varios servidores

Esto siempre se me olvida pero lo guardare aqui.

Muchas veces quiero correr un comando en varios servidores y no quiero entrar a cada uno por separado. La solucion es usar un ciclo sencillo.

Por ejemplo, digamos que quiero copiar el archivo /tmp/archivo.txt a /home/usuario/ en mis servidores server1, 2, 3... 5

Puedo ejecutar en server1:

for srv in server2 server3 server4 server5; do ssh $srv 'cp /tmp/archivo.txt /home/usuario/' ; done

Esto usara ssh para conectarse y correr el comando en cada server. Si tienes llaves de ssh configuradas no necesitaras un password.

miércoles, 19 de agosto de 2009

Perdi mi password de MySQL!

No me paso a mi pero ya me ha tocado verlo varias veces y solucionarlo es muy facil. El unico inconveniente es que tendras que detener MySQL un par de veces.

Despues de hacer tu primer shutdown (si no puedes entonces reinicia tu servidor y asegurate que el proceso no inicia) ejecuta lo siguiente para iniciar tu server sin que requiera NINGUN password:
/usr/bin/mysqld_safe --user=mysql --skip-grant-tables --skip-networking &

nota que por seguridad tampoco aceptara conexiones fuera de tu host local (--skip-networking).

Ahora para cambiar el password a uno nuevo:
/usr/bin/mysqladmin -u root flush-privileges password "password_nuevo"

Por ultimo reinicia tu daemon de MySQL y tendra tu nuevo password:
service mysql restart

Rapido: reemplazo de texto en una serie de archivos

A menudo se tiene que reemplazar una frase o una palabra en una cantidad de archivos que hace imposible hacerlo a mano. Eso si sabes que archivos tienen lo que necesitas.

Con el comando que pondre aqui puedes sustituir una palabra o frase en un archivo SIN abrirlo para edicion... o en todos los archivos que se encuentren de acuerdo a tu criterio de busqueda.

Vamos a plantearlo como problema.

Problema: Quiero reemplazar el año 2008 por 2009 en todos los archivos .html de un site.

Puedes usar el siguiente comando:
find . -name "*.html" | xargs perl -pi -e 's/2008/2009/g'

Aqui estamos combinando busqueda de archivos con find + el comando xargs + una expresion en perl ejecutada directamente desde nuestro shell sin crear un script.

Usando find y xargs se pueden hacer todo tipo de cosas que iremos viendo eventualmente.

Rapido: Lista de queries en MySQL

Para mi es muy entretenido ver datos y que pega contra las bases de datos. En ausencia del famoso "mytop" (luego escribire de el) aqui hay una forma de ver la lista de todos los queries ejecutandose en la base de datos.

La lista se actualiza cada segundo:
# watch -n 1 mysqladmin --user=root --password= processlist

Notas:
1. Esto lo debes correr desde la linea de comandos, no desde el cliente de MySQL
2. para cambiar el intervalo de actualizacion cambia el valor de "n"
3. despues de "password=" debes poner el password de tu base de datos

Rapido: Calculadora en linea de comandos

Un dia estaba en una terminal y necesitaba una calculadora y como no encontre que hacer acabe recurriendo al celular sin embargo debe haber una mejor manera, no?

En RedHat / CentOS / Fedora puedes usar bc, ejemplo:
# bc -l
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
5*8
40
100/5
20.00000000000000000000


Para salir presiona Ctrl - D ... y listo

martes, 18 de agosto de 2009

Estadisticas sobre tu set de datos en MySQL

No se a ti pero a mi muchas veces me paso que en alguna junta me preguntaran "cuanto mide la base de datos??... y cuanto aumenta por dia/semana/mes?". Casi siempre la pregunta planteada por alguien que quiere saber mas que nada por curiosidad pero que te mete en un problema... y que tal si te preguntan sobre tablas especificas??!!

Contar numero de registros es facil pero que tal espacio utilizado en disco? si usas InnoDB entonces lo siguiente te servira.

Con el siguiente query puedes ver el numero de registros en TODA una base de datos, espacio en disco ocupado por datos, espacio ocupado por indices, espacio total y la relacion indices vs. datos.

Ejemplo usando la base de datos 'mysql'. Para usar la tuya solo cambia el final despues de TABLE_SCHEMA:

SELECT count(*) TABLES,
concat(round(sum(table_rows)/1000000,4),'M') rows,
concat(round(sum(data_length)/(1024*1024*1024),4),'G') DATA,
concat(round(sum(index_length)/(1024*1024*1024),4),'G') idx,
concat(round(sum(data_length+index_length)/(1024*1024*1024),4),'G') total_size,
round(sum(index_length)/sum(data_length),4) idxfrac
FROM information_schema.TABLES where TABLE_SCHEMA='mysql';

El query te va a regresar algo similar a:
+--------+---------+---------+---------+------------+---------+
| TABLES | rows | DATA | idx | total_size | idxfrac |+--------+---------+---------+---------+------------+---------+
| 17 | 0.0018M | 0.0004G | 0.0001G | 0.0005G | 0.1562 | +--------+---------+---------+---------+------------+---------+


Que tal si solo quieres el dato para una tabla en particular? Entonces usa esto:
SELECT count(*) TABLES, concat(round(sum(table_rows)/1000000,4),'M') rows, concat(round(sum(data_length)/(1024*1024*1024),4),'G') DATA, concat(round(sum(index_length)/(1024*1024*1024),4),'G') idx, concat(round(sum(data_length+index_length)/(1024*1024*1024),4),'G') total_size, round(sum(index_length)/sum(data_length),4) idxfrac FROM information_schema.TABLES where TABLE_SCHEMA='pm_beta' and TABLE_NAME='nombre_de_mi_tabla';

Y la salida sera:
+--------+---------+---------+---------+------------+---------+
| TABLES | rows | DATA | idx | total_size | idxfrac |+--------+---------+---------+---------+------------+---------+
| 1 | 8.9598M | 0.7090G | 1.0834G | 1.7923G | 1.5281 | +--------+---------+---------+---------+------------+---------+


Notese que cambie a una tabla que tuviera mas datos.

Ahora, vamos a ver como sacar el desgloze por cada base de datos limitando a 10 max:
SELECT count(*) TABLES, table_schema,concat(round(sum(table_rows)/1000000,4),'M') rows, concat(round(sum(data_length)/(1024*1024*1024),4),'G') DATA, concat(round(sum(index_length)/(1024*1024*1024),4),'G') idx, concat(round(sum(data_length+index_length)/(1024*1024*1024),4),'G') total_size, round(sum(index_length)/sum(data_length),4) idxfrac FROM information_schema.TABLES GROUP BY table_schema ORDER BY sum(data_length+index_length) DESC LIMIT 10;

Salida:
+--------+--------------------+------------+-----------+-----------+------------+---------+
| TABLES | table_schema | rows | DATA | idx | total_size | idxfrac |+--------+--------------------+------------+-----------+-----------+------------+---------+
| 358 | produccion | 7722.5668M | 411.1646G | 870.1474G | 1281.3120G | 2.1163 |
| 17 | mysql | 0.0018M | 0.0004G | 0.0001G | 0.0005G | 0.1562 |
| 6 | test | 0.0000M | 0.0000G | 0.0000G | 0.0000G | 4.0716 |
| 17 | information_schema | NULL | 0.0000G | 0.0000G | 0.0000G | NULL |
| 1 | maatkit | 0.0000M | 0.0000G | 0.0000G | 0.0000G | NULL |
|+--------+--------------------+------------+-----------+-----------+------------+---------+


Por ultimo vamos a ver como hacerlo para una sola tabla:
SELECT count(*) TABLES, TABLE_NAME, table_rows, concat(round(sum(data_length)/(1024*1024*1024),4),'G') DATA, concat(round(sum(index_length)/(1024*1024*1024),4),'G') idx, concat(round(sum(data_length+index_length)/(1024*1024*1024),4),'G') total_size, round(sum(index_length)/sum(data_length),4) idxfrac FROM information_schema.TABLES WHERE TABLE_SCHEMA='mi_base_de_datos' AND table_name = 'mi_tabla' group by TABLE_NAME;

Salida:
+--------+------------------------+------------+----------+-----------+------------+---------+
| TABLES | TABLE_NAME | table_rows | DATA | idx | total_size | idxfrac |+--------+------------------------+------------+----------+-----------+------------+---------+
| 1 | mi_tabla | 1209954640 | 75.8538G | 176.0356G | 251.8894G | 2.3207 |+--------+------------------------+------------+----------+-----------+------------+---------+

Si quieres ver todas las tablas o un grupo de tablas solo cambia lo siguiente:
table_name = 'mi_tabla'
por...
table_name like '%substring_en_mis_tablas%'

Con esto podras sacar muy buena informacion.... el formato de salida puede ser manipulado facilmente con php o perl y puedes correr tus comandos usando cron de manera que acumules nueva informacion cada dia o semana o mes segun prefieras.

aburrrrrrrrr........

Renombrar archivos en Windows, AKA yo vs. la camara digital

Por distintas razones ultimamente he tomado muchas fotos con mis camaras digitales y aunque no hay mucha opcion de entrada la realidad es que no me gustan los nombres de los archivos finales y eso dificulta saber el contexto de la foto al andar buscando archivos.

En mi caso por el tipo de fotos me interesa que el nombre contenga la fecha. Yo se que igual esta en las propiedades del archivo pero en alguna copiada esta cambia dependiendo del sistema.

Cual era el reto? renombrar cantidades grandes de archivos para que el nombre contenga la fecha y para esto usaremos la linea de comando de Windows o lo que muchos conocemos como el prompt de DOS.

Va el ejemplo... mi nombre original de archivo es:
- P1010963.JPG

En mi necedad insisto que quiero la fecha ahi por lo que quiero que el nombre final sea:
- P1010963_20090706_1143AM.JPG

Si es un nombre largo pero tiene lo que necesito y aunque muchos diran que el nombre puede ser solamente la fecha sinceramente si hay archivos con la misma fecha no quiero tener secuencias estilo nombre_archivo_[1...n]. Por lo mismo conservo el nombre original en el nuevo string.

Ahora la solucion:
1. abre un editor de texto
2. graba tu archivo como renombrar.bat (o cualquier otro nombre mientras la extension sea bat).
3. pega el siguiente codigo:
@ECHO OFF
FOR %%V IN (%1) DO FOR /F "tokens=1-6 delims=/: " %%J IN ("%%~tV") DO Rename "%%V" %%~nV_%%L%%J%%K_%%M%%N%%O%%~xV

4. graba tu archivo de nuevo
5. renombra archivos!

Como lo usaras? simplemente usa el command prompt o linea de comando de windows para llegar al directorio donde estan tus fotos o archivos a renombrar y ejecuta:
renombrar.bat *.JPG (o la extension de tus archivos)

Al final tendras todos los archivos con nombres nuevos solo que ojo, la fecha del archivo en si (propiedades) va a cambiar de la original a la del momento en que ejecutes el comando.

Ya esta... pruebalo en un directorio con algunos archivos y si te agrada usalo. Y si rompes algo no es mi culpa :)

UPDATE!!
Otra de mis inquietudes era usar la informacion del archivo (EXIF) para crear el nombre. Ahi se encuentran una cantidad ridicula de parametros pero los mas interesantes para mi causa son el modelo de la camara, la fecha y la hora.

Resulta que hay un programa freeware que se llama RenameMaster y aunque le falta en documentacion hace un buen trabajo.

Lo encuentras aqui

Como instalo un paquete de Perl?

Es tarde entonces va la opcion mas rapida. Obviamente desde la linea de comandos.

Primero iniciamos un shell de Perl:
perl -MCPAN -e shell

Si es la primera vez que lo corres te espera un setup de unos 5 minutos donde normalmente escogeras las opciones default.

Una vez qeu estas dentro del shell solo corres el comando "install nombre_del_paquete", ejemplo:
install Net::SNMP

Si no sabes que paquete requieres entonces te puedes pasar semanas viendo el repositorio de Perl en http://www.cpan.org/

Hay de todo y para todos.

Bajando paquetes con Yum sin instalar o actualizar

No se si habra muchos pero yo soy fan de 'yum'. Para los que no lo saben ese es el nombre del instalador y administrador de paquetes/programas/aplicaciones en Fedora, CentOS, RedHat (RHEL) y otras distros de Linux.

Una cosa que lo hace muy conveniente es que al usarlo resuelve todas las dependencias que se requieren. Por ejemplo:

# yum install vim-enhanced
---> Downloading header for vim-enhanced to pack into transaction set.
vim-enhanced-6.3.046-1.el 100% =========== 7.6 kB 00:00
---> Package vim-enhanced.x86_64 1:6.3.046-1.el4_7.5z set to be updated
--> Running transaction check
--> Processing Dependency: vim-common = 1:6.3.046-1.el4_7.5z for package: vim-enhanced
--> Restarting Dependency Resolution with new changes.
--> Populating transaction set with selected packages. Please wait.
---> Downloading header for vim-common to pack into transaction set.vim-common-6.3.046-1.el4_ 100% ============ 116 kB 00:00
---> Package vim-common.x86_64 1:6.3.046-1.el4_7.5z set to be updated
--> Running transaction check
Dependencies Resolved

Si bien todo es grandioso al hacer eso muchas veces pasa que el servidor con el que estamos trabajando no tiene acceso al mundo exterior para bajar paquetes nuevos (la seguridad es importante, verdad?).

Dependiendo de tu configuracion puede que al instalar algo en un server tengas una copia de los paquetes o instaladores en /var/cache/yum/[base/updates/extras/etc]/packages/ sin embargo el default no es asi.

Aqui entra la extension de Yum con nombre "downloadonly" o como dirian mis amigos "nomas bajalo".

Para usarlo primero tienes que instalar la extension usando:
yum -y install yum-downloadonly

Ya instalado el proceso es como instalar o actualizar un paquete pero agregando --downloadonly y opcionalmente una ubicacion para los archivos que se bajen. Si este ultimo no se especifica entonces todo se guarda en el directorio donde te encuentres.

Ejemplo:
yum [update/install] vim-enhanced -y --downloadonly --downloaddir=/tmp

Esto hara que se grabe vim-enhanced y sus dependencias en /tmp SIN instalarse. El proceso va a ser identico al de instalacion o actualizacion pero despues de bajar los paquetes aparecera un mensaje diciendo "exiting because --downloadonly specified".

Es importante mencionar que esto solo se ha hecho oficial en las versiones 5 de CentOS y RedHat (RHEL). Fedora ya lo tiene desde hace rato.

Suerte!

lunes, 17 de agosto de 2009

Respaldos [backups] en MySQL para los pobres

Casi todos los dias se presenta algo nuevo en mis instalaciones de MySQL. No son cosas malas, simplemente son gajes del oficio. Sobre todo considerando que las bases de datos que manejo estan rondando 1.5TB y alrededor de 40 millones de queries/consultas en un dia (para mi master, en mis esclavos sube al doble y en las bases de datos de reportes son ~110 millones al dia).

Uno de los problemas con ese volumen de datos y de trafico es hacer backups porque no hay un momento del dia en que se pueda decir que estamos en mantenimiento, al menos no donde trabajo! Supongo que es conveniente poner un banner en un homepage diciendo "El servicio no estara disponible de 1am a 4am"... quizas algun dia.

Existen varias soluciones para respaldar en MySQL. La mas conocida por estar incluida con el server es mysqldump.

El problema es que con eso se generan archivos de texto con los datos de las tablas y si algun dia pasas de los 200GB en tu base de datos te daras cuenta que importar tu base de datos de nuevo es algo que te llevara minimo 24hrs (dependiendo de tus discos, indices y otras variables).

La solucion? innodbbackup? no porque bloquea tus tablas mientras se estan copiando.

Para mi lo mas sencillo y que realmente es practico es realizar copias directas de archivos en formato binario. Mi proceso es:
1. Detener la replicacion en un esclavo (mysql -e "slave stop")
2. Detener el proceso de la base de datos (service mysql stop en Fedora, CentOS, RedHat)
3. Una vez que mysqld se detenga copiar todo /var/lib/mysql (cp -Rvf /var/lib/mysql /lugar/a/donde/quiero/copiar/)

En varias ocasiones he tomado cursos con gente de MySQL AB (no se como se llamen desde que los compro Sun y que Oracle compro a este) y aunque no recomiendan operaciones directas sobre archivos yo no he tenido ningun problema.

La gran ventaja es que puedo tomar los archivos binarios, copiarlos a otro servidor e iniciar una replica de la base de datos inmediatamente, sin importar archivos de texto, conservando mis grants, etc.

Otro truco que no es popular pero que es muy util con tablas en MyISAM es copiar los archivos sin detener el servidor SIEMPRE Y CUANDO no se esten modificando las tablas.

Si tienes tablas que mas que nada son de lectura las puedes copiar sin detener tu server simplemente ejecutando:
# cp -Rvf /var/lib/mysql/nombre_de_tu_BD/nombre_de_la_tabla.* /lugar/a/donde/quiero/copiar/)

Esta conectada la red en mi server o no?

Problema... aunque suene ridiculo, no se si esta conectado el cable de red en mi servidor.

Creanme que si sucede esto. ifconfig no dice mucho, /var/log/messages tampoco, dmesg menos porque la interfase existe... entonces que hago?

Pues el otro dia estaba en este dilema y no tenia acceso fisico al servidor y aunque tenia dos interfases de red solo una funcionaba. Teoria? cable malo... conexion defectuosa.... acaso no lo conectaron?

Entra al rescate el comando:
# mii-tool

que nos regresa:
eth0: negotiated 100baseTx-FD, link ok
eth1: negotiated 100baseTx-FD, link ok

lo interesante es que la intefase no tiene que estar configurada (IP asignado, etc) para responder al comando.

No se si a alguien le servira esto pero a mi me llevo horas resolver el problema... y efectivamente el cable estaba desconectado =/

El diff que no existe [o como restarle un archivo a otro]

Esta es mi primera entrada y la verdad mi unico objetivo es compartir lo que voy haciendo, encontrando, descubriendo y demas.

Bien dicen que cada dia se aprende algo y que la vida te da sorpresas.

Y bueno, el problema de hoy? Tengo dos archivos de texto y quiero que no contengan lineas iguales... porque? yo tengo mis razones y cada quien las suyas pero el caso es que despues de tratar de hacerlo con PHP (era lentiiiiiisimo!!!), Perl (- lento pero meh) y diff acabe con el famoso grep.

Ahi va la solucion, tengo dos archivos:
1. archivoBien.txt
2. archivoMal.txt

y lo que quiero es que mi archivo 1 no tenga nada que contenga mi archivo 2. Tan facil como correr el siguiente comando en Linux:
# grep -Fxvf archivoMal.txt archivoBien.txt

y listo, eso te dara el resultado. Quieres el resultado en un archivo nuevo? Redirecciona la salida asi:
# grep -Fxvf archivoMal.txt archivoBien.txt > archivoFinal.txt

Es todo... aburrrrrrrrrrr