Desbloquear Samsung Galaxy S I9000B (Code Unlock)
0Hace unos meses compre un smartphone Samsung Galaxy S, la version I-9000B, Brasilero… con la fantasmeada de “Fabricado en Tierra del Fuego”. Buen telefono, con Pantalla Super Amoled y TV digital como principales diferencias con el I9000. Hoy me vi en la necesidad de desbloquear el mismo para poder usarlo en otra prestadora, investigando no mas de 5 minutos en google y xda di con la solucion.
El método funciona con casi todos los Samsung Galaxy S (I9000 I900B I9003 etc) y tambien con los Samsung Galaxy S2 (SGS2)
Requisitos:
- Telefono ROOTEADO (Si no tenes el telefono rooteado, recorda que google es tu amigo)
- Algun explorador de archivos (File Manager) que permita ver archivos con permisos de ROOT (File Expert puede ser uno, o el que traen la mayoria de las ROMS modificadas tipo Cyanogenmod o similares)
- Placa de video (GPU) ATI RV 7×0 o bien una Nvidia CUDA…
- Windows… (Si, WINDOWS en la maquina que tenga esa placa de video, si no les gusta la idea pueden hablar con los desarrolladores y portar el codigo)
- Herramienta necesaria: http://www.multiupload.com/TH6X8RQ35P
Pasos
1- Obtener el archivo /efs/nv_data.bin y transferirlo a la PC donde van a ejecutar la herramienta (Video ATI/Nvidia). Esto pueden realizarlo directamente con el File Expert, pueden enviarlo por mail e incluso usar sshdroid y pasarlo por scp.
2- Ejecutar la herramienta, seleccionar el archivo nv_data.bin que copiamos desde el telefono, seleccionar nuestro modelo de telefono y generar el codigo de desbloqueo

Este proceso puede tomar unos segundos/minutos dependiendo del GPU que posean. Al finalizar les entregara el código de desbloqueo.
3- Apagar el teléfono y colocar un chip de otra compañía. En este punto el teléfono les debería pedir que inserten el código de desbloqueo. Aquí insertan el numero entregado por la herramienta. Si da error invalido y están seguros de que esta bien el código, no sigan intentando porque a la tercera vez se bloquea.
Si al poner otra sim, solo les muestra “Sim Incorrecta”, significa que el teléfono esta hard locked y este método no funcionará.
Zabbix-PostgreSQL Monitoreo de sesiones.
1Hace unos dias arranque con un pequeño script para el monitoreo de las sesiones en un motor de base de datos PostgreSQL (PostgreSQL Sessions Monitor). Ahora toca explicar como integrarlo directamente con un servidor de monitoreo Zabbix.
Para esta tarea se utilizo el mismo script pgmon, solo que modificamos la lina donde seteamos el OUTPUTFORMAT, para que por defecto no devuelva los resultados formateados para pantalla:
if [ "$OUTPUTFORMAT" == "" ]; then OUTPUTFORMAT=0 fi
En la linea 15, reemplazamos OUTPUTFORMAT=1 por OUTPUTFORMAT=0
La configuración puede varias segun la distribución linux utilizada. Lo primero que debermos hacer es crear un link a pgmon en alguna ubicacion contenida dentro de la variable de entorno PATH. En gentoo, el lugar ideal para estas aplicaciones de “terceros” es /opt/bin
mkdir /opt/bin ln -s /root/utils/scripts/monitoreo/pgmon /opt/bin/pgmon
El agente zabbix corre como el usuario del sistema zabbix. Para contabilizar las sesiones se realiza una conexión a la base de datos, por lo tanto el usuario que ejecute pgmon debe tener autenticación IDENT a PostgreSQL. Otra alternativa es utilizar sudo para permitir la ejecución de pgmon como otro usuario, en este caso lo ejecutaremos como root (No muy recomendable, seria mejor ejecutarlo como postgres).
Para dar acceso a zabbix a sudo, debemos modificar /etc/sudoers agregando la siguiente linea al final:
zabbix ALL=NOPASSWD: /opt/bin/pgmon
Ahora simplemente modificamos la configuracion del agente zabbix para crear el nuevo parametro de usuario (/etc/zabbix/zabbix_agentd.conf)
UserParameter=pgmon[*],sudo /opt/bin/pgmon \$1
El siguiente paso es configurar nuestro servidor zabbix para que consulte este nuevo “monitor”, para ellos nos dirigimos a nuestro panel zabbix -> Configuración -> Equipos -> Monitores del equipo donde corre nuestro PostgreSQL.
Aquí abrimos “Crear monitor” (Parte superior derecha) y configuramos un nuevo monitor con el valor “pgmon[-s -n]” para contabilizar las sesiones totales. También podemos crear un monitor para ver las sesiones actualmente ejecutando alguna consulta (Busy Sessions), aquí debemos usar el monitor “pgmon[-s -b]“.
Ejemplo de pantalla de configuración de monitor:

Configuración de nuevo monitor
Una vez que tenemos los monitores configurados y corriendo, podremos crear un grafico que plasme la cantidad de sesiones abiertas (persistentes) sobre la cantidad de sesiones realmente ejecutando consultas.
PostgreSQL Sessions Monitor
1Hace unos días me encontré con la necesidad de contar con una herramienta rápida para chequear las sesiones actualmente corriendo en una base de datos PostgreSQL. La idea era contar con una herramienta para monitorear por consola y adicionalmente poder integrarlo al servidor Zabbix que actualmente tengo corriendo para monitorear todos los servidores.
Como no encontre nada simple decidí hacer un pequeñisimo script para pode monitorear algunas variables. La versión inicial monitorea:
El código se explica por si solo y es bastante simple.
#!/bin/bash # # Script para monitoreo de servidor PostgreSQL # # @author Emiliano Romero <emilianoromero@gmail.com> # @www about.me/reflex # Config Vars DEFAULTDB="db3g" DEFAULTUSER="postgres" DEFAULTPASSWD="" # Static Vars VERSION="0.1rc1" if [ "$OUTPUTFORMAT" == "" ]; then OUTPUTFORMAT=1 fi ###################### # FUNTIONS # ###################### # Help function showhelp { echo "PGMon $VERSION" echo "Usage PGMon [MonitorType] [TypeOptions]" echo " -s: Sessions Monitor" echo " -n: Shows number of open connections" echo " -b: Shows number of busy connections" echo " -d: Shows list of running queries" echo " -p <pid>: Shows detailed information about <pid> PostgreSQL process" echo " -h: Shows this help information" echo " " echo "Examples: pgmon -s -d" echo " pgmon -s -p 1234" } # Sessions Monitor function sessionmon { case $2 in # Count sessions -n) sessionmon_count ;; -b) sessionmon_running ;; -d) sessionmon_detail $* ;; -p) sessionmon_pid $* ;; *) showhelp ;; esac } # Sessions Total Count function sessionmon_count { sesscount=$(SQLExec 'SELECT COUNT(*) FROM "pg_stat_activity";') formatecho "Sessions Number:" $sesscount } # Sessions Busy Count function sessionmon_running { sesscount=$(SQLExec 'SELECT COUNT(*) FROM "pg_stat_activity" where "current_query"!='"'"'<IDLE>'"'"';') formatecho "Busy Sessions:" $sesscount } # Sessions Detail function sessionmon_detail { cols=$(tput cols) sqllen=$(($cols - 60)) if [ $sqllen -lt 1 ]; then sqllen=1 fi SQLExec_formated 'SELECT "datname" as database,"procpid" as pid,"usename", substring(replace(regexp_replace("current_query",E'"'"'/\\*.*\\*/'"'"','"'"''"'"'),E'"'"'\n'"'"','"'"''"'"') from 1 for '"$sqllen"') as query, date_trunc('"'"'seconds'"'"', (now() - "query_start")) as running, "client_addr" as ip from "pg_stat_activity" where "current_query" != '"'"'<IDLE>'"'"' order by running desc;' } # Sessions PID Details function sessionmon_pid { COLOR_TITLE="\e[1;37m" COLOR_VALUE="\e[0;37m" DATA=$(SQLExec 'SELECT *,date_trunc('"'"'seconds'"'"', (now() - "query_start")) as running FROM "pg_stat_activity" where "procpid"='"$3"'') #datid|datname|procpid|usesysid|usename|current_query|waiting|xact_start|query_start|backend_start|client_addr|client_port # Split IFS="|"; declare -a Array=($DATA) datname=${Array[1]} procpid=${Array[2]} usename=${Array[4]} current_query=${Array[5]} waiting=${Array[6]} xact_start=${Array[7]} query_start=${Array[8]} backend_start=${Array[9]} client_addr=${Array[10]} client_port=${Array[11]} running=${Array[12]} echo -e "\e[1mPostgreSQL PID \e[1;32m$procpid \e[0m\e[1mdetails\e[0m" echo -e "${COLOR_TITLE}Username: ${COLOR_VALUE}$usename \t\t${COLOR_TITLE}IP: ${COLOR_VALUE}$client_addr:$client_port" echo -e "${COLOR_TITLE}Database: ${COLOR_VALUE}$datname" echo -e "${COLOR_TITLE}Waiting: ${COLOR_VALUE}$waiting" echo -e "${COLOR_TITLE}Connection Start: ${COLOR_VALUE}$backend_start" echo -e "${COLOR_TITLE}Running: \e[1;31m$running" echo -e "${COLOR_TITLE}SQL Query ${COLOR_VALUE}" echo -e "$current_query" } #SQLExec function SQLExec { echo "$1" | psql -tA -U $DEFAULTUSER $DEFAULTDB } # SQLExec for printing function SQLExec_formated { echo "$1" | psql -U $DEFAULTUSER $DEFAULTDB } # FormatEcho <text> <value> function formatecho { if [ $OUTPUTFORMAT -eq 0 ]; then echo $2 else echo "$1 $2" fi } #################### # MAIN # #################### case $1 in -s) sessionmon $* ;; -h|*) showhelp ;; esac
Si necesitamos que el script largue los resultados de la cantidad de sesiones limpio (Sin titulo), simplemente seteamos la variable OUTPUTFORMAT=0.
OUTPUTFORMAT=0 ./pgmon -s -b
En estos días subo un nuevo Post para integrarlo con zabbix.
Arch Sound with intel HD 5 series (3400)
1Hace ya un tiempo me motivaron a probar la distribucion linux ARCH. La verdad no fue muy fácil el pasaje, es una distribución mucho mas limpia donde hay que configurar gran parte a mano.
Uno de los primeros problemas que tuve con mi maquina laborar (DELL OPTIPLEX 980) fue el tema del sonido.
La configuración del sonido en ARCH, aunque es “”"”manual”"” es muy sencilla. Simplemente tenemos que ejecutar:
pacman -S alsa-utils
y luego
alsaconf
Con algunas placas de sonido Intel HDA alsaconf no detecta la misma: “No supported PnP or PCI card found”
alsaconf mantiene una lista de placas de sonido con sus respectivos módulos. Varias de las placas Intel HDA no se encuentran en esta base de datos. La solución mas sencilla es agregar a mano la misma.
Para ello buscamos el pciid (numero hexadecimal que identifica nuestra placa de sonido)
$ lspci -nn | grep Audio 00:1b.0 Audio device [0403]: Intel Corporation 5 Series/3400 Series Chipset High Definition Audio [8086:3b56] (rev 05)
Luego simplemente agregamos la misma al archivo /var/tmp/alsaconf.cards. Para esto debemos agregar la linea “PCI: 0×8086=0x3b56″ justo abajo de la linea “snd-hda-intel.o”. Notar que la linea tiene los dos numeros hexadecimales que sacamos de lspci -nn formateados.
Las lineas en cuestion quedarian de la siguiente manera:
snd-hda-intel.o PCI: 0x8086=0x3b56
Ahora solo necesitamos volver a ejecutar alsaconf y nuestra placa sera detectada y configurada.
Encriptación SSL para servicios HTTP que no lo soportan
1Hace unos días me encontré con el problema de encriptar mediante SSL trafico HTTP de un webservice/Aplicación que originalmente no tiene soporte para SSL.
Llegue a una solución realmente rapida y sencilla que no implica que los desarrolladores modifiquen la aplicacion gracias a NGINX.
La idea es crear un bloque server SSL en NGINX y gracias al modulo proxy y el parametro proxy_pass, redireccionar todo el trafico hacia el servidor interno sin SSL. Esto permite mantener la aplicacion y la implementación intacta, agregando encriptación SSL en la comunicacion entre el cliente y nuestro reverse proxy (NGINX).
Ejemplo de configuración:
#ssl portion server { listen 443; server_name ws.example.com; # configuracion SSL especifica ssl on; ssl_certificate /etc/ssl/nginx/nginx.pem; ssl_certificate_key /etc/ssl/nginx/nginx.key; access_log /var/log/nginx/ws.example.com.ssl_access_log main; error_log /var/log/nginx/ws.example.com.ssl_error_log error; # WebServices URI location / { proxy_pass http://192.168.1.2; } }
En el ejemplo creamos un vhost ws.example.com con la opción SSL y solicitamos todo el trafico dirigido a ese vhost al servidor alojado en la IP interna 192.168.1.2.
Adicionalmente se podría solo redireccionar alguna URI especifica modificando el bloque location.
Bash check process running time
0Chequear el tiempo de ejecución de un proceso en linux
En estos dias me encontre con el problema de chequear cuanto tiempo lleva corriendo un script en linux para poder matarlo si excede x cantidad de segundos.
Para ello cree una pequeña funcion en bash:
function checkRunningTime {
PTIME=$(ls -ld /proc/$1 | awk '{ print $6" "$7 }')
T1=$(date +%s -d "$PTIME")
T2=$(date +%s)
((DIFF=T2 - T1))
echo $DIFF
}
Para utilizarla solo se le pasa como parametro el PID. Para sacar el PID con un simple ps | awk se obtiene.
checkRunningTime `ps aux | grep "nombreproceso" | grep -v "grep" |awk '{ print $2 }'`
NGINX: Failover y Balanceo de carga web
0Introducción
nginx [engine x] es un servidor proxys inverso HTTP (reverse proxy) y tambien un mail proxy escrito por Igor Sysoev. A la fecha ya lleva mas de 5 años corriendo en sitios de trafico alto.
Caracteristicas básicas HTTP
- Brindar archivos estaticos y de indice (autoindexing), cache de open file descriptors.
- Acelera el proceso de proxy inverso con cache. Balanceo de carga y fail-over simple.
- Soporte acelerado de servidores remotos FastCGI con cache.Balanceo de carga y fail-over simple.
- Arquitectura modular. Filtros, GZIP, chunked responses, XSLT, filtro de redimencionado de imagenes, Server Side Include (SSI) entre varios servidores remotos.
- Soporte SSL y TLS SNI
Otras caracteristicas HTTP
- Servidores virtuales basados en IP o nombres.
- Soporte para conexiones keep-alive.
- Configuración flexible.
- Reconfiguración y actualizaciones sin interrupción de servicio.
- Formateo de logs y rotación rápida.
- Redirección de codigos de error 3xx-5xx
- Modulo Rewrite.
- Control de acceso basado en IP y Basic HTTP AUTH.
- Metodo PUT, DELETE, MKCOL, COPY y MOVE soportados.
- FLV streaming;
- Limite de velocidad/BW.
- Limitacion de conexiones desde un mismo cliente.
- Perl embebido.
Experiencia personal
Decidi escribir un post sobre Nginx debido a mi experiencia personal con el mismo en la compañia donde actualmente trabajo. En la misma nuestros clientes usan un gran sistema web para el monitoreo de moviles (PHP+Mapserver), con muchas aplicaciones repartidas entre varios servidores. En el pasado se utilizaba Apache con mod_proxy para poder redireccionar pedidos a otros servidores desde el mismo dominio. Teniamos aproximadamente 180 sesiones (Threads) de apache corriendo constantemente y era muy facil pisar el techo de los 250 (Maximo debido a limitaciones de memoria del servidor). Por ello se decide instalar nginx on-the-top, incluso hoy en nuestro ambiente de produccion nginx se encuentra corriendo en el mismo servidor que apache. Con Nginx se logro reducir a 25 las sesiones/threads concurrente en apache.
Instalación
La instalacion es bastante sencilla (http://wiki.nginx.org/Install). Personalmente uso Gentoo en mis servidores por lo que la instalacion la realizo desde el gestor de paquetes emerge
emerge -uv nginx
Configuración
No es el objetivo hoy ir muy profundo en la configuración de nginx, la verdad que la wiki en ingles esta bastante completa y posee ejemplos de todo tipo (http://wiki.nginx.org/Configuration)
El archivo de configuración por default se ubica en /etc/nginx/nginx.conf y se divide en bloques. El mas importante para nosotros en este momento es el bloque http { }. Alli tenemos todas las configuraciones referentes al protocolo http, time outs, errores, limites, etc. Dentro del mismo podemos tener 1-n bloques server { }. Los mismos son similares a los bloques VirtualHost de apache.
server {
listen 80;
server_name www.domain.com;
index index.html;
root /home/domain.com
}
Cada VirtualHost/Server podemos hacerlo escuchar en el puerto que nosotros deseemos con el parametro listen. server_name especifica el virtualHost al que hacemos referencia en este bloque. Podemos agregar mas de un dominio/host separados por espacio.
El parametro index indica el archivo que hara de indice y el parametro root es el DocumentRoot donde se ubicaran todos los archivos del host.
Otra característica interesante de la configuración es el parámetro include que nos permite incluir otros archivos dentro de la configuración. Esto permite armar una configuración simil a la de apache y sus virtualhosts.
Con la configuración de ejemplo ya tendriamos al dominio “www.domain.com” contestando peticiones y obteniendo el contenido desde /home/domain.com. Siempre contenido estatico.
Usos
Servidor Proxy inverso & Fail-Over
La principal caracteristica de NGINX es la de un reverse proxy server. Esto permite que el cliente haga una peticion a nuestro srevidor proxy y el mismo decida quien responde a esta peticion. Para esta funcion de utiliza el modulo HTTPProxyModule de Nginx que nos da el parametro proxy_pass (http://wiki.nginx.org/HttpProxyModule#proxy_pass). Este parametro debe ir dentro del bloque location (http://wiki.nginx.org/HttpCoreModule#location). El mismo básicamente nos permite especificar una ubicación especifica dentro de un server (Similar a apache).
El parametro proxy_pass permite redireccionar la peticion a otra URL, la misma puede ser una IP, DNS o bien un upstream server. Estos ultimos se definen en el bloque upstream dentro del bloque http.
upstream server_one {
server 172.16.102.3;
server 172.16.102.11 backup;
}
upstream server_two {
server 172.16.102.11;
server 172.16.102.3 backup;
}
server {
listen 80;
server_name www.domain.com;
location /web/ {
proxy_pass http://server_one;
}
location /images/ {
proxy_pass http://server_two;
}
}
En la configuración de ejemplo he definido dos upstream servers, ambos con dos servidores internamente, uno como activo y el otro servidor como backup. Esto significa que el segundo no respondera ninguna petición hasta que el primero no caiga.
Luego dentro de nuestro server de ejemplo he definido dos locations (web y images) que seran atendidas por los dos upstream servers que definimos anteriormente.
Asi si accediéramos a http://www.domain.com/web/archivo.php el mismo inicialmente seria solicitado al servidor web http://172.16.102.3/web/archivo.php. Si este estuviera caido, nginx automáticamente redireccionaria las peticiones a http://172.16.102.11/web/archivo.php. Lo mismo sucede con /images/.
Balanceo de carga
Para realizar balanceo de carga la configuración es igual a la anterior, el único que cambio que necesitamos hacer es quitar el parámetro backup del ultimo servidor del bloque upstream en cuestión. Adicionalmente podemos utilizar el parametro weight para darle mas peso a un servidor que a otro y realizar un balanceo de carga mas controlado.
upstream server_one {
server 172.16.102.3 weight=2;
server 172.16.102.11;
}
En el ejemplo tendriamos 2 de cada 3 peticiones siendo enviadas a 172.16.102.3 y la ultima restante a 172.16.102.11. Esto tambien incluye failover, cuando nginx detecta que un servidor esta fuera de linea automaticamente lo remueve del pool de servidores. El mismo es chequeado periodicamente para comprobar si ha vuelto a estar online.
Resumen
Nginx es una aplicación muy potente que nos da fail-over, balanceo de carga y escabilidad ya que podemos agregar nuevos servidores on-the-fly. Personalmente he testeado nginx con 1024 conexiones concurrentes y no superaba los 250 MB de ram consumidos. Agregando mas worker_process tranquilamente podriamos responder muchas mas peticiones.
Adicionalmente posee un sistema de cacheo muy configurable, actualmente utilizo NGINX en las oficinas remotas de la compañia. Esto me permite cachear localmente todo el contenido estatico (Imagenes, JavaScripts, html, css, etc) y por el enlace de datos (Internet o MPLS) solicitar las paginas dinámicas PHP que necesitan acceso a nuestra base de datos principal. Asi mantengo el procesamiento centralizado, ahorro ancho de banda y aumento la velocidad de respuesta notablemente. Prometo tocar mas en profundo esta solución en las próximas semanas, con ejemplos y todo.
Duda o comentarios? Abajo podes comentar.
PostgreSQL Server Replication Hot-StandBy
0Este mini-howto de como replicar dos servidores PostgreSQL surge debido a las Charlas IRC que estan siendo dictadas en el canal IRC del Linux User Group MENdoza (Lugmen irc://irc.freenode.net/lugmen). Cuando se me pregunto si estaba interesado en dar una charla me parecio interesante tocar el tema de PostgreSQL debido al desconocimiento general sobre las capacidades de este motor de base de datos Objeto-Relacional, que poco tiene que envidiarle a los monstruos propietarios (Informix, Oracle, etc).
PostgreSQL es un sistema Open Source bajo la licencia PostgreSQL License. Libre de uso y modificación.
Que es PostgreSQL ?
- Queries Complejos
- Foreign Keys
- Triggers
- Views
- Integridad transaccional
- Control de concurrencia
Y el motor lo podemos extender a nuestro gusto y placer de varias formas:
- Creando nuevos “Data Types”
- Creando nuestras propias funciones
- Operadores
- Métodos de indexación
- Lenguajes propios de procedimientos almacenados (Store Procedures)
- Extensiones en C (Shared libreries)
El post se va a centrar en replicación pero antes es necesario explicar un poco el funcionamiento de PostgreSQL y algunos terminos importantes
TableSpace: Es un contenedor de base de datos, cuando se crea un tablespace se le especifica la ubicacion dentro del filesystem del sistema operativo (Basicamente un directorio)
Cluster: Es una instancia de un servidor PostgreSql que contiene tablespaces y que escucha en determinado puerto. En una misma maquina se pueden tener varios clusters corriendo a la vez.
WAL o Write-Ahead Logging: Es un metodo estandar para asegurar la integridad de los datos. Todos los cambios a los archivos de datos solo son escritos en disco luego de que han sido logueados en un medio de almacenamiento permanente.
Esto ultimo permite que si el servidor se cae cuando se estaban escribiendo los datos en los archivos de datos, se puede recuperar desde los archivos WAL. Es muy similar a los Logical Logs que utilizan otros motores.
Para el almacenamiento de archivos PostgreSQL se basa en el filesystem donde esta hosteado (http://www.postgresql.org/docs/9.0/interactive/storage-file-layout.html). Dentro del cluster (/var/lib/postgresql/<version>/data) se encuentran los archivos de configuración y los logs.
La caracteristica que vamos a ver es Hot-Standby replication que es una funcion nueva en PostgreSQL 9.0 (PostgreSQL 8.3 solo soporta stand-by replication)
Replication
Vamos a ver dos tipos de replicacion
Warm-StandBy: Permite tener un servidor con los mismos datos que el servidor principal, el mismo se esta replicando constantemente y esta esperando a que lo activemos como primario
En este tipo de replicación NO podemos acceder al servidor secundario, osea que no podemos consultar los datos contenidos en el mismo.
Hot-Standby: Se basa en mantener un servidor secundario replicado con el servidor principal. Pero se permiten conexiones y hacer consulta de datos al servidor secundario
Este tipo de replicación es muy util para sistemas en los que se utiliza mucho procesamiento para la emision de reportes. Entonces podemos tener un servidor para insertar y modificar datos y 1 o mas servidores para realizar consultas y reportes
Lo primero que hay que tener en cuenta para replicar PostgreSQL es que todas las maquinas que participen en la replicación tienen que tener la misma arquitectura
ej: Ambos servidores deben ser Intel/Amd (x86) de 64 bits. No se podria mezclar un servidor de 32 bits con uno de 64.
Lo primero que debemos hacer para lograr la replicación es llevar el servidor secundario a un estado lo mas cercano posible al servidor primario.
Esto se realiza copiando el cluster completo de una maquina a otra. Esto incluye el archivo de configuración, por lo que segun el caso pueden ser necesarios algunos cambios en los archivos de configuración.
Aqui hay que tener en cuenta que copiar un cluster que este online va a resultar en un cluster duplicado inconsistente esto es debido a que mientras copiamos el cluster los archivos del mismo seguramente cambiaran.
El tema de la inconsistencia del cluster que acabamos de copiar lo podemos solucionar con los archivos WALs.
PostgreSQL genera segmentos Wals de 16 MB o cada ciertos intervalos de tiempo (Todo configurable), si almacenamos todos los segmentos Wals que se generaron mientras copiabamos el cluster (osea todos los cambios que se hicieron en los datos), podemos reproducir los mismos en el cluster inconsistente hasta llevarlo al ultimo punto consistente.
Este metodo es el mas usado para la realización de backups, ya que un dump de una base de datos grande demora mucho tiempo en ser recuperado.
WAL Archiving / Backup Inicial / Warm-StandBy
Para realizar este tipo de copiado de cluster en caliente necesitamos activar “WAL archiving” en el cluster primario.
Para ello en el archivo de configuracion (postgresql.conf) debemos habilitar el parametro archive_mode
archive_mode = on
Esto indica que se realizara el guardado de los segmentos WALs, adicionalmente debemos setear archive_command,este ultimo es el comando que se ejecutara cada vez que se tenga un nuevo segmento wal.
archive_command = "cp -i %p /mnt/server/archivedir/%f"
si se fijan estoy pasando como parametro %p y %f
%p es la ubicación del archivo Wal que se genero y %f es el nombre del mismo
Aqui lo que estamos haciendo es copiar los segmentos wals al directorio /mnt/server/archivedir/. Esto podria ser un mountpoint NFS por red, asi podriamos estar enviando los segmentos cuando se general al servidor secundario. Tambien podria usarse SCP para copiar los archivos, en este ultimo hay que tener en cuenta de generar las ssh-keys.
Esto es todo lo necesario desde el lado del servidor principal por ahora.
Ahora en el servidor Secundario para reprocesar archivos WALs hay que setear el cluster secundario en recovery mode. Para ello simplemente creamos un archivo recovery.conf con el siguiente contenido:
standby_mode = 'on' restore_command = 'cp /path/to/archive/%f $p' trigger_file = '/path/to/trigger_file'
standby_mode = ‘on’ permite que el motor se quede esperando nuevos segmentos WALs hasta que encuentre el trigger_file
restore_command es el comando a ejecutarse cada ve que se necesite un nuevo WAL
Los archivos de los segmentos Wals tienen un nombre correlativo, postgreSQL ira recuperando todos los archivos, si el comando restore_command devuelve un valor distinto de 0 va a reintentar con ese mismo archivo hasta que este disponible
Entonces lo ideal es desde el servidor primario enviar los segmentos Wals al servidor secundario y en este colocar como restore_command un simple ‘cp /path/to/archive/%f $p’ aca el significado de %f y %p es el mismo que comentamos anteriormente.
Una vez que tenemos todo configurado, debemos indicar al cluster primario que se va a realizar un backup, esto permite marcar un punto de inicio y un punto de fin para obtener consistencia.
Esto se realiza ejecutando una consulta sql (funcion de postgresql) en el cluster primario:
echo "SELECT pg_start_backup('lugmen');" | pgsql -U postgres
Esto lo que hace es generar un flush de todos los Wals actuales a disco y marca el “punto de inicio” del copiado de datos.
Luego simplemente copiamos todos los archivos del cluster primario al cluster secundario
scp -rp /path/cluster_primario user@host:/path/cluster_secundario
Puede ser SCP, NFS, o lo que fuera, inclusive con un disco usb.
Mientras se realiza el copiado de los archivos, todos los segmentos wals tienen que estar siendo almacenados y copiados al servidor secundario, una vez que termina el copiado ejecutamos:
echo "SELECT pg_stop_backup();" | pgsql -U postgres
Con esto indicamos que se ha terminado y se marca el “punto de fin” para lograr la consistencia.
Luego simplemente iniciamos el cluster secundario y automaticamente (gracias al archivo recovery.conf) comenzara a procesar los archivos WALs hasta llegar a un punto consistente, aunque asi cuando llegue al punto consistente el servidor secundario, debido a “standby_mode = on“, continuara levantando nuevos archivos Wals que detecte en el directorio.
En modo recovery el motor de base de datos no permite conexiones, si queremos “levantar” el servidor para poder hacer consultas debemos crear el trigger_file. Cuando se detecta la existencia de este archivo, se levanta el motor en el ultimo punto consistente que se tiene.
Con esto logramos que el cluster secundario este replicado con el cluster primario. Efectivamente existe un atraso debido a que hay que esperar a que el cluster principal genere un nuevo segmento WAL. Estos tiempos son controlables gracias al parametro de configuracion: archive_timeout. Con el podemos especificar cada cuantos segundos queremos que se guarde un segmento Wal.
Si el parametro archive_timeout esta en 0 (Por defecto), significa que no se generaran archivos wals hasta que no se llenen los 16 MB que ocupa un segmento Wal. Este valor debera ser configurado teniendo en cuenta el retardo de datos que queremos tener (Tiempo maximo de perdida de datos) y el ancho de banda disponible para el copiado de los segmentos.
Hot-StandBy Replication
Ahora vamos a ver la nueva caracteristica de PostgreSQL que permite disminuir este tiempo a menos de 1 segundo gracias a streaming replication
A partir de la version 9.0 PostgreSQL incorpora la posibilidad de realizar el envio de WALs mediante un stream de datos. Esto permite tener el cluster secundario actualizado mucho mas rapido (Debajo de 1 segundo).
Para permitir a los clusters secundarios conectarse al cluster primario, debemos configurar la siguiente entrada en el archivo pg_hba.conf del servidor primario.
host replication replicationuser 192.168.1.110/32 md5
aca doy acceso a “replication” al usuario “replicationuser” desde la ip 192.168.1.110 mediante autenticacion md5
El usuario replication es un superuser que debemos crear en el cluster primario:
echo "CREATE ROLE replicationuser LOGIN WITH PASSWORD 'replication' SUPERUSER INHERIT CREATEDB CREATEROLE;" | pgsql -U postgres
Ahora debemos ir al archivo de configuracion del servidor principal y debemos indicar cuantos segmentos Wals mantendremos para el envio a los clusters secundarios y ademas cuantos clusters secundarios estaran conectados:
El primer parametro es max_wal_senders donde indicamos cuantos servidores secundarios se conectaran para replicarse, luego tenemos wal_keep_segments que indica la cantidad de segmentos que se guardaran para ser enviados a los clusters secundarios
Este parametro es importante ya que permite que ante una caida del enlace de comunicaciones, cuando se retoma la replicacion, el servidor secundario pueda sincronizarse nuevamente. Mientras mas grande el numero mas tiempo puede estar caida la comunicacion entre los servidores con el inconveniente de que ocupa mucho mas espacio en disco.
Con esto tendriamos configurado el servidor primario, ahora pasamos al secundario donde debemos configurar la conexion de replicación en el archivo recovery.conf
primary_conninfo = 'host=192.168.1.144 port=5432 user=replicationuser password=replication'
Aca simplemente le especificamos el string de conexion para la replicación, en el ejemplo el servidor principal esta en la ip 192.168.1.144.
Al tener primary_conninfo, cuando no se encuentran mas segmentos Wals en archivo (Exit code 1), el cluster secundario realiza una conexion al servidor primario y comienza a recibir un stream de informacion WAL.
En este punto podriamos tener un servidor StandBy replicado con un retardo de menos de un segundo (depende de la capacidad del servidor secundario y del enlace de comunicaciones)
Antes de levantar el motor secundario, vamos activar el modo Hot-standBy para que se nos permita hacer selects en el cluster secundario
En el servidor principal es necesario cambiar el parametro wal_level a “hot_standby”
En el servidor secundario debemos habilitar el parametro “hot_standby = on”
En este punto podemos levantar el servidor secundario y este deberia sincronizarse con el primario.
En el archivo de logs del servidor primario deberiamos ver:
2010-12-03 20:16:10 UTC LOG: entering standby mode
Con esto nos indica que el motor va a quedar en standby mode
2010-12-03 20:16:10 UTC LOG: consistent recovery state reached at 1E0/2A8984F8
Nos informa de la ultima transaccion consistente que posee.
2010-12-03 20:16:10 UTC LOG: database system is ready to accept read only connections
Aca indica que el parametro hot_standby esta en ‘on’
2010-12-03 20:16:10 UTC LOG: streaming replication successfully connected to primary
Indica que se pudo conectar con el servidor primario para realizar la replicación binaria por streaming.
En este punto ya podemos realizar consultas en ambos servidores. Si probamos hacer un insert en el servidor primario veremos como se espeja en el secundario. el tiempo que tarda en replicarse es imperceptible (menos de 1 segundo).
Tener en cuenta que al crear nuevos tablespaces o agregar funciones linkeadas a librerias externas (Shared Libraries) en el servidor secundario deben existir las librerias y los directorios de los tablespaces.