jueves 30 de julio de 2009

¿Adiós a CentOS?

CentOS es una distro Linux -nacida del código fuente del Red Hat Enterprise(RHEL)- el cual cobró fuerza cuando Red Hat comenzó a comercializar su sistema operativo por medio de lincencias de uso y de soporte. CentOS por su parte surge como una alternativa de software libre ofreciendo la calidad y robustes de RHEL sin pagar costosas licencias y pólizas de soporte sosteniéndo el proyecto únicamente a base de donaciones.

El día de hoy el equipo base de desarrolladores de este proyecto, hizo pública una carta dirigida a su fundador Lance Davis.

Julio 30, 2009 04:39 GMT

Carta abierta a Lance Davis de los miembros que desarrollan CentOS.

Es lamentable que nos veamos obligados a escribir esta carta no nos quedó otra opción. De algún tiempo a la fecha hemos tratado de arreglar estos problemas:

Parece que te arrastraste hacia un agujero ... y no es aceptable.

Por mucho tiempo diste por hecho que habría fondos para el proyecto CentOS; al día de hoy no hemos visto nada.

Sólo tú tienes control del dominio 'centos.org' sin nadie más delegado; no es lo apropiado.

Sólo tú, así parece, eres el único que tiene privilegios de 'Fundador' en los canales de IRC sin nadie más delegado; no es lo apropiado.

Cuando traté de comunicarme (Russ) a los números telefónicos de Linux UK o a tu número, he escuchado el mensaje 'Líneas temporalmente ocupadas' durante las últimas dos semanas. Finalmente ayer, me respondió una máquina contestadora en la cual te dejé un mensaje solicitando que me regreses la llamada con caracter urgente. Karanbir reportó que también te ha llamado dejándote mensajes sin respuesta.

Por favor no mates CentOS sólo por el hecho de tener miedo en querer compartir la administración del proyecto.

Está claro que el proyecto muere si todos los desarrolladores se van.

Contáctame de favor, o a cualquiera de los demás que firman esta carta para ponernos de acuerdo sobre la información arriba mencionada y mantener vivo el proyecto con el dominio 'centos.org'.

Firman,

Russ Herrold
Ralph Angenendt
Karanbir Singh
Jim Perrin
Donavan Nelson
Tim Verhoeven
Tru Huynh
Johnny Hughes


CentOS ha sido adoptado por empresas de todos los calibres demostrando su calidad, sería una verdadera pena que por actitudes de esta naturaleza pudiera ver su fin un proyecto tan bueno como este.

Vía
CentOS Linux Project In Trouble

Continuar leyendo...

miércoles 15 de julio de 2009

¿Quien bloqueó mi sesión?

Recientemente me encontré con el siguiente artículo de Natalka Roshak publicado en orafaq.com que espero les sea de utilidad.

Cuando un usuario o desarrollador te dice que tiene su sesión bloqueada, —entendiendo por bloqueo la ejecución de una instrucción DML la cual después de lanzarla deja de responder— sabes cuan útil puede ser identificar no solo quien lo está haciendo, sino también cual objeto es ó mejor aún, puedes identificar el registro exacto que tu sesión está esperando bloquear.

Creando el bloqueo

Usaré la tabla emp del esquema SCOTT. Abro una sesión de SQL*Plus y configuro los siguiente parámetros
SQL> set sqlprompt "SESION1> "
SESION1> set linesize 200

actualizo todos los registros
SESION1> update emp
  2  set sal=1000*1.05;

14 rows updated.

sin dar commit abro otra sesión de SQL*Plus actualizo la variable
SQL> set sqlprompt "SESION2> "
SESION2>

y en esta actualizo sólo un registro
SESION2> update emp
  2  set sal=1000
  3  where empno=7369;

después de presionar ENTER no regresa de immediato al prompt, he aquí el bloqueo.

Identificando la sesión que está bloqueando

En una nueva sesión de SQL*Plus revisas el contenido de v$lock que muestra los bloqueos que existen actualmente en la base así como la relación entre quien bloquea a quien aunque no de manera explícita
SQL> select * from v$lock;

ADDR     KADDR        SID TY     ID1     ID2   LMODE   REQUEST   CTIME   BLOCK
-------- -------- ------- -- ------- ------- ------- --------- ------- -------
........ ........ ....... .. ....... ....... ....... ......... ....... .......
2887B03C 2887B068     144 TX  196639    3891       0         6     323       0
0E3CBE90 0E3CBEC0     144 TM   69948       0       3         0     323       0
0E3CBE90 0E3CBEC0     137 TM   69948       0       3         0     570       0
27CF5D14 27CF5D54     137 TX  196639    3891       6         0     570       1

observa la última columna BLOCK, si una sesión mantiene un bloqueo que a su vez bloquea a otra verás que BLOCK=1. Llendo más allá, puedes ver cuál sesión es la que está siendo bloqueada comparando ID1 e ID2. La sesión bloqueada tendrá los mismos valores en ID1 e ID2 que la que bloquea, y, ya que está haciendo la petición de bloqueo que no puede obtener, tendrá REQUEST>0.

En el query anterior puedes ver que el SID 137 está bloqueando al SID 144. SID 137 corresponde a SESION1 y SID 144 es SESION2 que está bloqueada.

Para no hacer la comparación sólo viendo los datos de ese query puedes ejecutar lo siguiente
SQL> select l1.sid || ' ESTA BLOQUEANDO ' || l2.sid
  2  from v$lock l1, v$lock l2
  3  where l1.block = 1
  4  and l2.request > 0
  5  and l1.id1 = l2.id1
  6 and l1.id2 = l2.id2;

L1.SID||'ESTABLOQUEANDO'||L2.SID
-----------------------------------
137 ESTA BLOQUEANDO 144

ó mejor aún, si se incluye la tabla v$session la información es aún más legible
SQL> select s1.username || '@' || s1.machine
  2  || ' ( SID=' || s1.sid || ' ) esta bloqueando '
  3  || s2.username || '@' || s2.machine || ' ( SID=' || s2.sid || ' ) ' as estado_bloqueos
  4  from v$lock l1, v$session s1, v$lock l2, v$session s2
  5  where s1.sid = l1.sid
  6  and s2.sid = l2.sid
  7  and l1.block = 1
  8  and l2.request > 0
  9  and l1.id1 = l2.id1
 10  and l2.id2 = l2.id2;

ESTADO_BLOQUEOS
-------------------------------------------------------------------------------------------
SCOTT@TESTSERVER ( SID=137 ) esta bloqueando SCOTT@TESTSERVER ( SID=144 )

Hay aún más información en la tabla v$lock, pero para leerla, es neceario entender un poquito más sobre los tipos de bloqueos y los crípticas columnas ID1 e ID2

Tipo de bloqueo y las columnas ID1 / ID2

En este caso el tipo de bloqueo es DML exclusivo ya que fuí yo quien lanzó la instrucción que bloquea. Sin embargo, su puede obtener esta información de v$lock sin tanto esfuerzo.

Lo primero es ver la columna TYPE. Hay decenas de tipos de bloqueos, sin embargo, la gran mayoría son de sistema. Estos últimos por lo general son muy breves y no ayuda mucho ajustar el library cache, undo logs, etc. si te metes con v$lock.

Sólo hay tres tipos de bloqueos de usuario, TX, TM y UL. UL es un bloqueo definido por el usuario —aquel definido con el paquete DBMS_LOCK. TX es un bloqueo de transacción de registros; se obtiene cada vez que hay una transacción para alterar datos, sin importar la cantidad de objetos que intervendrán en esa transacción. Las columnas ID1 e ID2 apuntan a los segmentos de rollback y a la tabla de entradas de transacciones de esa transacción.

TM es un bloqueo DML. Se obtiene cada vez que un objeto es alterado. La columna ID1 identifica el objeto en cuestión.

Modos de bloqueo

Se puede ver más información observando los modos de bloqueo TM y TX. Las columnas LMODE y REQUEST usan ambas la misma numeración que los modos de bloqueo, en orden de exclusividad incremental: desde 0 para sin bloqueo, hasta 6 para bloqueo exclusivo. Una sesión debe hacerse de un bloqueo exclusivo TX para que pueda alterar los datos; LMODE será 6. Si no puede obtener el bloqueo exclusivo debido a que algunos de los registros que quiere alterar están bloqueados por otra sesión, entonces hará la petición TX en modo exclusivo; LMODE será 0 ya que no está bloqueando, y REQUEST será 6. Esto se puede observar en el query ejecutado anteriormente
ADDR     KADDR        SID TY     ID1     ID2    LMODE  REQUEST   CTIME   BLOCK
-------- -------- ------- -- ------- ------- -------- -------- ------- -------
2887B03C 2887B068     144 TX  196639    3891        0        6     323       0
27CF5D14 27CF5D54     137 TX  196639    3891        6        0     570       1

Observa en SESION2 que ID1 e ID2, la cual está solicitando un bloqueo TX (LMODE=0, REQUEST=6), apunta hacia las entradas de transacciones y rollback de SESION1 que es lo que permite determinar la sesión que bloquea a SESION2.

Es posible que te encuentres también con bloqueos TX en modo 4 de modo compartido(Shared). Si un bloqueo no encuentra ninguna entrada disponible en la Lista de Transacciones Invocadas(ITL - Interest Transaction List) y tiene registros que va a alterar, entonces la sesión obtiene un bloqueo TX en modo 4 mientras espera por la entrada(ITL). Si notas que hay contención sobre un objeto por bloqueos TX-4, es probable que necesites incrementar su parámetro INITRANS.

Los bloqueos TM generalmente son requeridos y adquiridos en modo 3, también llamado registro compartido exclusivo(Shared-Row Exclusive) y modo 6. Las operaciones DDL requieren de un bloqueo TM exclusivo. (Nótese que la instrucción CREATE TABLE no requiere de un bloqueo TM —y no lo necesita ya que el objeto en cuestión ¡no existe todavía!) Las operaciones DML requieren de un bloqueo Shared-Row Exclusive. De los registros seleccionados arriba sobre v$lock, puedes ver por lo niveles de bloqueo TM que son de tipo DML
ADDR     KADDR        SID TY      ID1      ID2   LMODE  REQUEST   CTIME   BLOCK
-------- -------- ------- -- -------- -------- ------- -------- ------- -------
0E3CBE90 0E3CBEC0     144 TM    69948        0       3        0     323       0
0E3CBE90 0E3CBEC0     137 TM    69948        0       3        0     570       0

Encontrando el objeto bloqueado

Ahora que sabemos que cada registro TM apunta a un objeto bloqueado, se puede usar el campo ID1 para identificarlo.
SQL> select object_name from dba_objects where object_id=69948;

OBJECT_NAME
---------------------------------------------------------------
EMP

A veces es suficiente con sólo saber de cuál objeto se trata; sin embargo, su puede ahondar aún más, identificando no solo el objeto, sino también el bloque de datos e incluso el registro exacto por el que espera SESION2.

Encontrando el registro bloqueado

Esta información se obtiene de v$session mediante la entrada de la sesión bloqueada
SQL> select row_wait_obj#, row_wait_file#, row_wait_block#, row_wait_row#
  2  from v$session
  3  where sid=144;

ROW_WAIT_OBJ# ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW#
------------- -------------- --------------- -------------
        69948              4             147             0

esto regresa el ID del objeto, el número relativo de archivo, el bloque en el archivo de datos y el registro en el bloque que está esperando la sesión. Si estos datos te suenan conocidos, es porque estos son los cuatro componentes de un ROWID extendido. Se puede construir el ROWID extendido de dicho registro a partir de estos componentes usando el paquete DBMS_ROWID. La función ROWID_CREATE toma esos datos como argumentos para regresar el ROWID
SQL> select do.object_name, row_wait_obj#, row_wait_file#, row_wait_block#, row_wait_row#,
  2  dbms_rowid.rowid_create(1, row_wait_obj#, row_wait_file#, row_wait_block#, row_wait_row#)
  3  from v$session s, dba_objects do
  4  where sid = 144
  5  and s.row_wait_obj# = do.object_id;

OBJECT_NAM ROW_WAIT_OBJ# ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW# DBMS_ROWID.ROWID_C
---------- ------------- -------------- --------------- ------------- ------------------
EMP                69948              4             147             0 AAARE8AAEAAAACTAAA

con el cual podemos inspeccionar directamente el registro
SQL> select * from scott.emp where rowid='AAARE8AAEAAAACTAAA';

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 17-DEC-80        800                    20


Con lo anterior puedes identificar una sesión que está bloqueando y cómo llegar hasta el registro que está esperando la sesión bloqueada.

Continuar leyendo...

lunes 6 de julio de 2009

Qué es una 'fork bomb' y como prevenirla

En términos computacionales, 'fork' es la referencia a cuando un proceso(denominado proceso padre) crea una copia de sí mismo(proceso hijo). En ambientes multihilos esto significa que el hilo en ejecución(padre) es duplicado(hijo).

Una operación 'fork' aparta un espacio de memoria para el hijo. Este último, es una copia exacta de todos los segmentos de memoria del proceso padre, y, a pesar de que se trate de una implementación semántica copy-on-write, la memoria física podría no ser asignada(p.e. ambos procesos podrían llegar a compartir los mismos segmentos de memoria física durante algún tiempo). Tanto el proceso padre como el proceso hijo poseen los mismos segmentos de código, pero se ejecutan uno independiente del otro.

Teniendo una breve idea de lo que significa 'fork' a nivel de sistema operativo, 'fork bomb' es un ataque de tipo Denegación de Servicio o DoS (Denial of Service) en inglés, que implementa la operación fork (o una funcionalidad equivalente).


Una 'fork bomb' no se trata de un virus ya que no infecta otros programas o documentos, tampoco se trata de un gusano ya que no usa los recusos de red de la máquina para esparcirse, entra más bien en la categoría de 'wabbit'. El término 'wabbit' se atribuye probablemente a la pronunciación que hace Elmer Gruñón(caricaturas de Bugs Bunny) -en la versión en inglés- queriendo decir 'rabbit', que en español significa conejo y que al igual que los conejos una 'fork bomb' tiene la habilidad de multiplicarse rápidamente y "tumbar"(incapacitar) un sistema que confía en la asunción(generalmente válida) de que los programas y procesos que puede ejecutar simultáneamente tienen un límite.

Esta crea rápidamente una gran cantidad de procesos con el fin de saturar los espacios disponibles en la lista de procesos que guarda el sistema operativo. Si esta se satura, no podrá ejecutarse otro programa hasta que termine otro proceso y aún si esto sucediera, no es muy probable que este programa se ejecute ya que cada una de las instancias de la bomba tratarán por sí mismas de ocupar cualquier espacio disponible.

El siguiente código muestra la que podría considerarse una de las 'fork bomb' más elegantes. Presentada por Jaromil como una pieza de arte de código abierto en 2002. Ejecutas los siguientes 13 caracteres en un shell tipo Unix como bash o zsh.
:(){ :|:& };:

Lo cual significa
:()    # define ':' -- lo que sea que digamos ':', haz esto:
{      # inicio de lo que dijimos que tiene que hacer ':'
  :    # carga otra copia de la función ':' en memoria...
  |    # ...lo cual será entrada para...
  :    # ...otra copia de la función ':', que tiene que cargarse en memoria
       # (por lo tanto, ':|:' sencillamente carga dos copias de ':' como sea que ':' se llame)
  &    # libera las funciones -- si matan la primera ':', todas las demás que esta inició NO          deberían auto-matarse
}      # fin de lo que hace ':'
;      # Habiendo definido ':', ahora debería...
:      # ...llamar a ':', iniciando una reacción en cadena: cada ':' iniciará dos más.

Dado que ':' es un nombre arbitrario para la función, una versión más entendible sería:
forkbomb(){ forkbomb|forkbomb & };forkbomb

Otros ejemplos.
Versión en Windows usando lenguaje batch
%0|%0

ó un ejemplo que reaccione rápidamente
:s
start %0
%0|%0
goto :s

un poema en Perl
fork while fork

en Haskell
import Control.Monad
import System.Posix.Process

forkBomb = forever $ forkProcess forkBomb

en Python
import os

while True:
os.fork()

en Ruby
loop { fork }


Prevención

Una manera de prevenirlas es limitando el número de procesos que puede manejar un usuario. Cuando un proceso intente crear uno nuevo y el usuario esté al límite de procesos permitidos, este fallará. Los administradores deben configurar este tope lo suficientemente bajo de tal manera que si todos los usuarios lanzan una bomba simultáneamente, queden suficientes recursos para evitar el desastre; lo cual es prácticamente improbable(que todos los usuarios al mismo tiempo lancen una bomba).

Los sistemas tipo Unix, usualmente tienen un límite de procesos controlado por el comando de shell ulimit. Los kernels Linux configuran y respetan la variable RLIMIT(límite de recursos) de un proceso. De igual manera tanto en Linux como en *BSD puedes editar el archivo de configuración de pam_limits: /etc/security/limits.conf y agregar la siguiente línea. Sin embargo, verifica que está habilitado ya que no todas las distribuciones de Linux vienen con pam_limits configurado por default.
<os_user> hard nproc 200

Si no tienes PAM habilitado intenta poniendo la siguiente línea en tu archivo de configuración /etc/profile.conf
ulimit -u 200


Limitar el número de procesos que un proceso puede crear no previene de una 'fork bomb' ya que se quedarán ahí a la espera de crear más y más procesos. Un sistema que distribuya los recursos por cuota compartiendo los recursos del proceso padre podría funcionar, aunque este tipo de sistemas no son muy comunes.

Fuentes
Fork bomb
How to: Prevent a fork bomb by limiting user process


Continuar leyendo...

jueves 2 de julio de 2009

De cuando el botón 'Finish' del Oracle Database Configuration Asistant (dbca) en 11g no funciona

Hace un par de días me pidieron cambiar una base de datos que estaba montada en una lap con Windows XP y 11g a un servidor con Solaris 10 y mismo motor (11g), trabajo para no más de medio día -dije yo-. Pues bien, dejé haciendo un export en la lap y puse a transferir la instalación y parches al servidor. Configuré el ambiente en Solaris, levanté el ambiente X en mi máquina con Cygwin y ejecuté la instalación gráfica(dbca), me tomé mi tiempo para configurar todo lo requerido y cuando finalmente llegué a la última pantalla y presioné el botón 'Finish' me doy cuenta de que no aparece ni hace nada, dudando de si me había hecho falta algo -cosa que no es posible sino no puedes avanzar- me regresé ingénuamente a revisar cada pantalla y todo estaba en orden(como era de esperarse).


Cerré el instalador y lo volví a lanzar con la esperanza de que esta vez si funcionara pero no fue así. Lo lancé una tercera vez pero en esta ocasión puse atención a cualquier detalle, pista o mensaje de error, siendo lo siguiente lo primero que observé
$ dbca
Warning: Cannot convert string "-monotype-arial-regular-r-normal--*-140-*-*-p-*-iso8859-1" to type FontStruct

¿Un aviso no un mensaje de error propiamente podría ser el casusante de dicho comportamiento? Veamos que dice el archivo log [ORACLE_BASE]/cfgtoollogs/dbca/<dbname>/trace.log
[AWT-EventQueue-0] [11:20:29:828] [DBCAWizard.onFinish:1139] m_bFinishClicked: true
[AWT-EventQueue-0] [11:20:30:2] [DBCAWizard.onFinish:1139] m_bFinishClicked: true
[AWT-EventQueue-0] [11:20:35:126] [SQLEngine.done:1958] Done called

El evento de presionar el botón si aparace ¿Entonces por qué no continua?

Buscando en Metalink información al respecto encontré la nota 727290.1 la cual básicamente te dice que el problema está en tu cliente X(Cygwin en mi caso) y te sugieren que intentes con otro cliente X o con VNC.

¿Cambiar de ambiente X en tu máquina sólo porque un insignificante botón no continua con la creación de la base? No se justifica -creo yo- y por la parte de VNC pues tampoco es opción ya que no soy quien administra el servidor.

Opción 2, crear la base con el dbca usando el modo "silencioso". Antes de usar la opción 2 es necesario crear un template -para no tener que especificar variable por variable en la línea de comandos- con el mismo dbca. Ejecuta el asistente, configura todo lo necesario y en la última pantalla selecciona la opción "Save as a Database Template" presiona el botón 'Finish' y listo.


Desde línea de comando ejecutas
$ dbca -silent -createDatabase -templateName testdb.dbc -gdbName testdb -sid testdb -sysPassword syspass -systemPassword systempass -emConfiguration LOCAL -dbsnmpPassword dbsnmppass -sysmanPassword sysmanpass

el cual sólo te mostrará el porcentaje de avance y los eventos más significativos
Copying database files
DBCA_PROGRESS : 1%
DBCA_PROGRESS : 3%
DBCA_PROGRESS : 11%
DBCA_PROGRESS : 18%
DBCA_PROGRESS : 26%
DBCA_PROGRESS : 37%
Creating and starting Oracle instance
DBCA_PROGRESS : 40%
DBCA_PROGRESS : 45%
DBCA_PROGRESS : 50%
DBCA_PROGRESS : 55%
DBCA_PROGRESS : 56%
DBCA_PROGRESS : 60%
DBCA_PROGRESS : 62%
Completing Database Creation
DBCA_PROGRESS : 66%
DBCA_PROGRESS : 70%
DBCA_PROGRESS : 73%
DBCA_PROGRESS : 77%
DBCA_PROGRESS : 88%
DBCA_PROGRESS : 100%
Database creation complete. For details check the logfiles at:
 /opt/oracle/product/cfgtoollogs/dbca/testdb.
Database Information:
Global Database Name:testdb
System Identifier(SID):testdb

The Database Control URL is https://<SERVER_NAME>:1158/em

Management Repository has been placed in secure mode wherein Enterprise Manager data will be encrypted. The encryption key has been placed in the file: /opt/oracle/product/rdbms/11.1.0.7.0/testserver_testdb/sysman/config/emkey.ora. Please ensure this file is backed up as the encrypted data will become unusable if this file is lost.

Lo anterior se graba en el archivo
$ cat [ORACLE_BASE]/cfgtoollogs/dbca/<DBNAME>/testdb.log

Listo, base creada y lista para lanzar el import -por la tarde noche- en el servidor con el archivo dmp generado en la lap. Por supuesto que ya no quedó en medio día como lo tenía previsto, pero la experiencia cuenta para próximas ocasiones.

La nota de Metalink que puse arriba, menciona que este comportamiento puede presentarse también en 10g versiones 10.2.0.1 a 10.2.0.4 y en cualquier plataforma.

Continuar leyendo...