jueves, 26 de agosto de 2010

Bug en PostfixAdmin con base de datos Mysql. Too many connections

He detectado un mini bug en PostfixAdmin que hace que la plataforma rechace conexiones a la base de datos, debido a que genera una saturación de conexiones al motor, Mysql en este caso. El problema radica principalmente en que las funciones de dicho programa solamente abren las conexiones a la base de datos y no las cierran una vez finalizada la query o la operación correspondiente a la base de datos. Con ello, satura el spool de conexiones del motor, dejándolo inhabilitado para operar.

Read More PostfixAdmin es una herramienta, desarrollada en PHP, que permite administrar casillas de correo electrónico para postfix, con utilidades y aplicaciones bastante interesantes, como el Backup, la generación de cuentas y test de la misma online, etc. Bastante recomendable. De hecho tiene soporte multi base de datos, etc. Para mayor información de la app pueden recurrir al sitio http://postfixadmin.sourceforge.net/ y mirar más características de éste.
Particularmente en esta ocasión comentaré acerca de un problema que se generó al utilizar esta plataforma. El proyecto requería una inyección masiva de cuentas online y para ello se modificó la estructura del programa, aprovechando que es free software, con licencia GNU. Al requerir una inyección masiva y continua de cuentas de correo en el sistema, nos percatamos, gracias al control de errores que creé para la plataforma superior que utilizaba esta herramienta, que la plataforma en un momento dejó de crear cuentas. Al revisar los errores de la plataforma, comprobamos un "Too many connections" en el log. Al revisar en Mysql las conexiones activas, vimos que había superado las 170 mil conexiones y no permitía seguir ingresando más.

mysql> show status like '%onn%';
+------------------------------------+------------+
| Variable_name                     | Value      |
+------------------------------------+------------+
| Aborted_connects                | 14            |
| Connections                          | 171083  |
| Max_used_connections      | 31           |
| Ssl_client_connects            | 0              |
| Ssl_connect_renegotiates | 0              |
| Ssl_finished_connects       | 0              |
| Threads_connected            | 4              |
+------------------------------------+------------+
7 rows in set (0.00 sec)

Lo primero que hice fue aumentar la variable max_connections que estaba en 100 (es un mysql  5.0.77) y la setee en 500, para lo cual usé
SET GLOBAL max_connections=500;
Luego de eso al ver que solamente le di algo más de tiempo antes de caer, revisé el code del postfixadmin que estaba utilizando (create-mailbox.php) y revisé la parte referente a las conexiones a la base y certifiqué que las conexiones que se abrían no eran cerradas correctamente, creando un exceso de conexiones sin utilizar y que quedaban abiertas,  impidiendo el buen funcionamiento del motor.
El programa usa una función llamada db_connect() para realizar la conexión y db_query para realizar las consultas a la base. Dichas funciones están incluídas en el archivo functions.inc.php, cuyos cambios detallo a continuación:
//
// db_query
// Action: Sends a query to the database and returns query result and number of rows
// Call: db_query (string query)
// Optional parameter: $ignore_errors = TRUE, used by upgrade.php
//
function db_query ($query, $ignore_errors = 0)
{
global $CONF;
global $DEBUG_TEXT;
$result = "";
$number_rows = "";
static $link;
$error_text = "";
if ($ignore_errors) $DEBUG_TEXT = "";

if (!is_resource($link)) $link = db_connect ();

if ($CONF['database_type'] == "mysql") $result = @mysql_query ($query, $link)
or $error_text = "
DEBUG INFORMATION:
Invalid query: " . mysql_error($link) . "$DEBUG_TEXT";
if ($CONF['database_type'] == "mysqli") $result = @mysqli_query ($link, $query)
or $error_text = "
DEBUG INFORMATION:
Invalid query: " . mysqli_error($link) . "$DEBUG_TEXT";
if ($CONF['database_type'] == "pgsql")
{
$result = @pg_query ($link, $query)
or $error_text = "
DEBUG INFORMATION:
Invalid query: " . pg_last_error() . "$DEBUG_TEXT";
}
if ($error_text != "" && $ignore_errors == 0) die($error_text);

if ($error_text == "") {
if (preg_match("/^SELECT/i", trim($query)))
{
// if $query was a SELECT statement check the number of rows with [database_type]_num_rows ().
if ($CONF['database_type'] == "mysql") $number_rows = mysql_num_rows ($result);
if ($CONF['database_type'] == "mysqli") $number_rows = mysqli_num_rows ($result);
if ($CONF['database_type'] == "pgsql") $number_rows = pg_num_rows ($result);
}
else
{
// if $query was something else, UPDATE, DELETE or INSERT check the number of rows with
// [database_type]_affected_rows ().
if ($CONF['database_type'] == "mysql") $number_rows = mysql_affected_rows ($link);
if ($CONF['database_type'] == "mysqli") $number_rows = mysqli_affected_rows ($link);
if ($CONF['database_type'] == "pgsql") $number_rows = pg_affected_rows ($result);
}
}

$return = array (
"result" => $result,
"rows" => $number_rows,
"error" => $error_text
);
if ($CONF['database_type'] == "mysql") mysql_close($link); //  <---- LINEA AGREGADA
if ($CONF['database_type'] == "mysqli") mysqli_close($link); // <--- LINEA AGREGADA
return $return;
}

Además dado que no solo db_query abría conexiones, se tuvo que modificar también la funcion escape_string.

/**
* Clean a string, escaping any meta characters that could be
* used to disrupt an SQL string. i.e. "'" => "\'" etc.
*
* @param String (or Array)
* @return String (or Array) of cleaned data, suitable for use within an SQL
*    statement.
*/
function escape_string ($string)
{
global $CONF;
// if the string is actually an array, do a recursive cleaning.
// Note, the array keys are not cleaned.
if(is_array($string)) {
$clean = array();
foreach(array_keys($string) as $row) {
$clean[$row] = escape_string($string[$row]);
}
return $clean;
}
if (get_magic_quotes_gpc ())
{
$string = stripslashes($string);
}
if (!is_numeric($string))
{
$link = db_connect();
if ($CONF['database_type'] == "mysql")
{
$escaped_string = mysql_real_escape_string($string, $link);
}
if ($CONF['database_type'] == "mysqli")
{
$escaped_string = mysqli_real_escape_string($link, $string);
}
if ($CONF['database_type'] == "pgsql")
{
// php 5.2+ allows for $link to be specified.
if (version_compare(phpversion(), "5.2.0", ">="))
{
$escaped_string = pg_escape_string($link, $string);
}
else
{
$escaped_string = pg_escape_string($string);
}
}
if ($CONF['database_type'] == "mysql") mysql_close($link); //  <---- LINEA AGREGADA
if ($CONF['database_type'] == "mysqli") mysqli_close($link); // <--- LINEA AGREGADA
}
else
{
$escaped_string = $string;
}
return $escaped_string;
}

Con ello se solucionó el problema y ya no tengo caídas en la base por saturación de conexiones. Cabe destacar que la modificación se realizó solo para mysql y mysqli, pero si se quiere agregar para PostgreSQL solo se debe añadir el close de pg en las partes comentadas. Si alguien más tuvo este problema, ahora tiene la solución...ganancias del software libre, no?

Leer más...

jueves, 5 de agosto de 2010

Google Cierra Wave...Cronica de una Muerte Anunciada?

En información publicada en el blog de Google, se señala que, aun cuando había sido presentada con bombos y platillos (de hecho linkee la presentación en mi blog unos cuantos artículos atrás) y aun teniendo unas aplicaciones tremendas en cuanto a experiencia de usuario, IMHO, cerrará las cuentas y el proyecto de Google Wave. Esto debido a que, si bien varios teníamos cuenta y, personalmente, regalé bastantes invitaciones, el sistema no tuvo la aceptación que se esperaba en la gente. Particularmente creo que las redes sociales tienen mucho que ver en el tema, en cuanto, si bien no tienen la misma experiencia que tenía Wave, tienen aplicaciones con un final bastante parecido pero usando una vía distinta.

De hecho, en Facebook, donde no tengo cuenta ni tendré, puedes "compartir" fotografías. Insisto, no en la manera que lo hacía Wave, pero con el mismo efecto final. El drag and drop de Wave no ha sido replicado aun en ninguna red social, pero la gente normalmente lo ve como una ganancia secundaria o de menor importancia. El tema de ver lo que el otro escribía, en línea, si bien es un chiche, la finalidad de ello es que el mensaje completo le llegue al destinatario, lo cual lo tienen en modalidad chat las páginas de ese estilo.Y asi, el resto de las apps de Wave.
Personalmente creo que Wave era un buen producto, pero careció de difusión, por un lado. Por otro lado, y aqui es donde creo que falló la visión y la ambición superó la realidad, Wave estaba diseñado para ser un protocolo, en realidad, era o es un protocolo de comunicación. De hecho la idea era que otras empresas crearan sus clientes para ese protocolo. Ese protocolo tenía la finalidad de reemplazar el IMAP, POP3 y demases protocolos de correo electrónico. Ahi es donde estuvo el error. Inicialmente debieron buscar la manera de integrarse a esos protocolos, en vez de desbancarlos, puesto que éstos llevan bastante tiempo con nosotros y serán muy difíciles de erradicar, por no decir casi imposible, a menos que alguna revolución tecnológica nos encamine a otro lado.
Pero como siempre, Google no pierde todo lo que hace y en el mismo artículo del blog de Google se recuerda que el código de varias aplicaciones es código abierto, por lo que cualquier otro individuo podrá añadirlo a sus aplicaciones. Además Google lo integrará con Gmail y en otras apps propias de ellos.
Leer más...

sábado, 5 de junio de 2010

Problema con Libreria php_pgsql en php 5.2.13

Instalando php 5.2 en un servidor (no se podia instalar 5.3 por la "vejez" del código existente), resultó que no cargaba la librería para conectar con PostgreSql. La version instalada en ese momento era la 5.2.13. El error que mostraba era el clasico "unable to load dynamic library". El tamaño de la librería php_pgsql en php 5.2.13 es de aproximadamente 95 KB y esa es la que presenta problemas para cargar. La solución, al menos la que se obtuvo para este caso, fue realizar el downgrade de la libreria a la que aparece en la version de Php 5.2.5, la cual, en tamaño, dobla a su sucesora, con cerca de 135 KB. Se copia esa librería en la carpeta /PHP/ext o su correspondiente para tu sistema y listo. Solo reinicias el servidor web de tu uso y listo.
Revisando php.net para la explicación de esta situación, encontré que la razón se debía a que la libreríaphp_pgsql.dll suministrada desde 2.5.6 en adelante está dinámicamente linkeada con libpq.dll, a diferencia de la 5.2.5 donde estaba estáticamente linkeada y no tenía esa dependencia. Leer más...

lunes, 31 de mayo de 2010

FastCgi Error 1413

En una asesoría realizada hace poco, detecté un error que tenía una instalación de PHP con FastCgi para IIS V6.0.
Al parecer el MSI de php 5.3.2 no creó bien las entradas en el archivo de configuración fcgiext.ini en c:\windows\system32\inetsvr.
El error que lanzaba en pantalla el navegador era el siguiente:

FastCGI Error
The FastCGI Handler was unable to process the request.
--------------------------------------------------------------------------------
Error Details:
Could not find entry for "php" on site 1 in [Types] section.
Error Number: 1413 (0x80070585).
Error Description: Invalid index.
HTTP Error 500 - Server Error.
Internet Information Services (IIS)

Para solucionar ese error hay que verificar que el archivo fcgiext.ini mencionado anteriormente tenga las entradas correctas para PHP.
Las entradas que yo puse para ese servidor y que funcionaron, fueron las siguientes:
En la línea final del archivo aparecía
-------------
[Types]
-------------
hay que agregar las siguientes líneas para que quede asi:
-----------------------
[Types]
php=PHP

[PHP]
ExePath=UNIDAD:\RUTA AL PHP\php-cgi.exe      --->(Ej     C:\PHP, H:\CARPETA1\PHP)
InstanceMaxRequests=10000
ActivityTimeout=600
RequestTimeout=600
EnvironmentVars=PHP_FCGI_MAX_REQUESTS:10000,PHPRC:UNIDAD:\RUTA AL PHP\     -------->(Ej: C:\PHP\)

----------------------------------------

Obviamente los parámetros InstanceMaxRequests, ActivityTimeout y RequestTimeout pueden ser modificados a su libre albedrío.
Las EnvironmentVars tienen que quedar con los parametros de su sistema. Recuerden reemplazar las palabras UNIDAD y RUTA AL PHP por sus datos. Leer más...

viernes, 14 de mayo de 2010

FUDCon Latam 2010, en Chile

Desde el 15 al 17 de julio se realizara en nuestro pais el FUDCon (Fedora Users and Developers Conference) para Latinoamerica. En esta ocasion, la sede para el evento sera la Universidad Central, patrocinada por su comunidad Linux Ucentux.
Se espera contar con la presencia de bastantes adeptos al sistema Linux, en especial a su distribucion Fedora. Se esperan variadas charlas respecto al SO, entre las que destacan la de Gnome 3.0 e Infraestructura de LATAM, entre otras que se iran confirmando. Puedes ver con mayor detalle consejos, ubicaciones, avisos, alojamientos y transporte en la pagina de FedoraProject  disponible para este evento. Si quieres colaborar, en la misma tambien puedes encontrar la informacion para hacerlo.
Leer más...

lunes, 26 de abril de 2010

Recuperar database SQL SERVER 2000 usando archivo de datos MDF sin archivo de LOG o LDF.

Una mala jugada de los respaldos de las bases de datos en mi trabajo ocasionó que se perdieran 2 archivos de log (LDF) de las bases de datos de SQL SERVER 2000. Teniendo solamente los MDF en la mano es imposible rescatar la BD. Por ello tuve que empezar a investigar como se podía rescatar la estrucutura y datos. En varias búsquedas realizadas, logré armar un procedimiento para tal efecto: Rescatar una base de datos solamente con el MDF, prescindiendo del LDF o Log File.

A continuación los pasos para ello:

Lo primero es regenerar el archivo de log. Como hacerlo? Fácil. En el motor o servidor que quieres albergar la BD, crea una base de datos con el mismo nombre que la que quieres rescatar.

Luego, baja el motor y borra el MDF creado y reemplázalo por el respaldado. Lógicamente tiene que tener el mismo nombre de archivo.

Luego sube el motor.

Si todo lo anterior está ok, debe aparecer tu nueva base de datos en modo "sospechoso" o "suspect".

Utilizando algún Query Analizer, conéctate a la base de datos MASTER del motor y ejecuta la siguiente sentencia, para poder cambiar algunos datos de sistema directamente:


SP_CONFIGURE 'Allow updates',1

;

RECONFIGURE WITH OVERRIDE

;

UPDATE sysdatabases SET status = 32768 WHERE name='Mi_base_de_datos_suspect'


Me detengo particularmente en la última sentencia, para hacer hincapié en que deben poner el nombre de su base de datos en el "name" del WHERE.


Habiendo terminado lo anterior, abran el administrador corporativo o enterprise Manager del SQL SERVER.

En la sección de las bases de datos, esa base debería aparecer en modo de emergencia y en color plomo.

Bien, con ello, ejecuten el importador/exportador de datos del motor, seleccionen la base de datos que quieren rescatar (la que está en modo emergencia), la base de datos de destino y luego elijan la o las tablas que quieren recuperar...y listo!!!!

Con ello comenzarán a rescatar los datos de ella y luego la pueden transportar, modificar o lo que quieran.

Este proceso que recopilé de varios lugares, funciona perfecto y puedes respirar tranquilo...
Leer más...

viernes, 12 de marzo de 2010

Fiefox Personas

firefox-logoFirefox Personas es una utilidad nueva de la versión 3.6 de Firefox que permite incorporar un tema al navegador de manera fácil y rápida sin instalaciones. Es posible bajar tu skin de la galería donde encontrarás más de 50 mil diseños disponibles.

Acabo de instalar la versión 3.6 de mi navegador Firefox y grata es la sorpresa de "vestir" a tu navegador. Aun cuando los Themes o Skins para el navegador están hace tiempo, su uso no es muy masivo dado que hay que instar dicho tema y además alteran todo el navegador. Hoy Firefox Personas permite tener un skin para el navegador, que es la herramienta que más utilizamos mientras estamos conectados a nuestras máquinas, de manera muy fácil y rápida.
Para hacer uso de esta nueva utilidad, están obligados a actualizar su versión de navegador a la 3.6 o superior (dependiendo de cuando lean esto...). Luego si no realizan la "vestimenta" del navegador al momento de actualizar, pueden ingresar al sitio "personas" de Firefox y aplicar el tema que quieran. Incluso pueden crear fácilmente el de ustedes, personalizado. Es recomendable revisar las PUF's para entender de mejor manera, aunque, insisto, es muy fácil. Aunque no todo es perfecto, pues echo de menos un buscador de "personas" más personalizado que recorrer la galería completa. Por último, pueden acceder y cambiar fácilmente sus skins desde el "Zorro" que está en la sección inferior izquierda de su navegador, tal como muestra la imagen de mi navegador "recién vestido"

firefox_personas

Disfruten de esta nueva aplicación de Firefox, que sigue haciendo de la navegación internet algo nuevo día a día...vamos Fast Followers, a ver que muestran ahora. :)
Leer más...