Jul 30, 2009

Redes Privadas Virtuales, ya a la venta... con RA-MA!

Después de varios meses, la editorial RA-MA ya ha puesto a la venta mi libro "Redes Privadas Virtuales", tanto en su página web como en distintas librerías (El Corte Inglés, La Casa del Libro, etc.). También estará a la venta en América a través de distintos coeditores y distribuidores.


El libro consta de un total de siete capítulos distribuidos a lo largo de 860 páginas:

  1. Introducción a las VPNs
  2. Administración de redes TCP/IP
  3. Criptografía de clave pública
  4. IPSec
  5. PPTP
  6. L2TP/IPSec
  7. SSL

Jul 28, 2009

Almacenamiento compartido en red: GFS2 + GNBD (I)

En el presente artículo vamos a desarrollar una arquitectura de almacenamiento compartido a la que accederán de forma concurrente un par de máquinas. Las pruebas van a ser realizadas bajo un sistema operativo de tipo CentOS 5.3.

El área de datos sobre el que se configurará el acceso compartido será un volumen lógico (LogVol00) cuyo sistema de archivos será GFS2 (Global File System 2).

GFS es un sistema de ficheros nativo creado por Red Hat y distribuido bajo licencia GNU, que puede ser utilizado de forma local (como por ejemplo ext3) o en cluster, de manera que varios nodos puedan estar trabajando simultáneamente sobre él sin peligro a que se corrompan los datos. El tamaño máximo de almacenamiento que soporta GFS2 es de 8 EB.

En la figura siguiente puede observarse que el espacio de almacenamiento compartido se instalará sobre la máquina centos01, el cual será exportado a los nodos centos02 y centos03 a través del driver GNBD (Global Network Block Device). GNBD proporciona acceso a almacenamiento en bloques a través de TCP/IP.


Cada una de las máquinas deberá tener registrado los nombres de todos los nodos en el fichero /etc/hosts.
[... ~]# cat /etc/hosts
...
192.168.1.11 centos01 centos01.local
192.168.1.12 centos02 centos02.local
192.168.1.13 centos03 centos03.local

SELinux deberá estar desactivado en los tres nodos, al igual que iptables. En el siguiente artículo veremos la forma de configurarlos correctamente para que no interfieran en el sistema de almacenamiento.
[... ~]# setenforce 0

[... ~]# service iptables stop

Lo primero que vamos a hacer es instalar el software necesario en los tres nodos (será el mismo para todos).
[... ~]# yum install lvm2-cluster rgmanager gfs2-utils gnbd kmod-gnbd

Seguidamente vamos a crear el volumen lógico que se empleará como espacio compartido en centos01, empleando para ello una partición de 64 GB que ya tendremos creada previamente y etiquetada como Linux LVM.
[root@centos01 ~]# fdisk -l
...
Disposit. Inicio Comienzo Fin Bloques Id Sistema
/dev/sdb1 1 8354 67103473+ 8e Linux LVM

Primero habrá que crear un volumen físico sobre esa partición, después el grupo de volúmenes (VolGroup01) y por último el volumen lógico (LogVol00).
[root@centos01 ~]# pvcreate /dev/sdb1

[root@centos01 ~]# vgcreate VolGroup01 /dev/sdb1

[root@centos01 ~]# lvcreate -l 100%FREE -n LogVol00 VolGroup01

Una vez que ya se tiene el volumen lógico, crearemos dentro de él un sistema de archivos GFS2. El parámetro lock_dlm indica el protocolo de bloqueo a emplear, siendo lock_dlm (DLM - Distributed Lock Manager) para el caso de acceso concurrente y lock_nolock para el caso de acceso de un único nodo. Con la opción de -t se especifica el nombre del cluster y el nombre que le queremos dar al sistema de archivos, y con la opción -j se indica el número de nodos que accederán concurrentemente al sistema de archivos.
[root@centos01 ~]# mkfs.gfs2 -p lock_dlm -t mycluster:gfs2_data -j 3 /dev/VolGroup01/LogVol00

A continuación se va a crear un archivo denominado cluster.conf el cual refleje la arquitectura de los tres nodos (deberá estar situado en las tres máquinas).
[... ~]# cat /etc/cluster/cluster.conf
<?xml version="1.0"?>
<cluster alias="mycluster" config_version="1" name="mycluster">
<fence_daemon clean_start="0" post_fail_delay="0" post_join_delay="3"/>
<clusternodes>
<clusternode name="centos01.local" nodeid="1" votes="1">
<fence>
<method name="1">
<device ipaddress="centos01.local" name="gnbd"/>
</method>
</fence>
</clusternode>
<clusternode name="centos02.local" nodeid="2" votes="1">
<fence>
<method name="1">
<device ipaddress="centos02.local" name="gnbd"/>
</method>
</fence>
</clusternode>
<clusternode name="centos03.local" nodeid="3" votes="1">
<fence>
<method name="1">
<device ipaddress="centos03.local" name="gnbd"/>
</method>
</fence>
</clusternode>
</clusternodes>
<cman/>
<fencedevices>
<fencedevice agent="fence_gnbd" name="gnbd" servers="centos01.local"/>
</fencedevices>
<rm>
<failoverdomains>
<failoverdomain name="failover_centos01" nofailback="0" ordered="0" restricted="1">
<failoverdomainnode name="centos01.local" priority="1"/>
</failoverdomain>
<failoverdomain name="failover_centos02" nofailback="0" ordered="0" restricted="1">
<failoverdomainnode name="centos02.local" priority="1"/>
</failoverdomain>
<failoverdomain name="failover_centos03" nofailback="0" ordered="0" restricted="1">
<failoverdomainnode name="centos03.local" priority="1"/>
</failoverdomain>
</failoverdomains>
<resources>
<script file="/etc/init.d/gnbd_client" name="gnbd_client"/>
<script file="/etc/init.d/gnbd_server" name="gnbd_server"/>
<clusterfs device="/dev/gnbd/gfs2_gnbd" force_unmount="0" fsid="45982" fstype="gfs2" mountpoint="/mnt/gfs2_gnbd/" name="resource_gfs2_gnbd" self_fence="0"/>
</resources>
<service autostart="1" domain="failover_centos01" exclusive="0" name="service_centos01">
<script ref="gnbd_server"/>
</service>
<service autostart="1" domain="failover_centos02" exclusive="0" name="service_centos02">
<script ref="gnbd_client">
<clusterfs ref="resource_gfs2_gnbd"/>
</script>
</service>
<service autostart="1" domain="failover_centos03" exclusive="0" name="service_centos03">
<script ref="gnbd_client">
<clusterfs ref="resource_gfs2_gnbd"/>
</script>
</service>
</rm>
</cluster>

En una primera sección (clusternodes) se definen los nombres de los tres nodos (clusternode name) así como su método fencing asociado. El fencing viene a ser una especie de protección o de bloqueo que hace que los nodos esperen en esa "barrera" para poder sincronizarse.

Para el caso del ejemplo anterior, se ha declarado un dispositivo (fencedevice) de tipo fence_gnbd en el nodo centos01, y a continuación se ha asociado a los tres nodos (fence). Esto significa que si por ejemplo iniciamos centos01, éste esperará a finalizar su proceso de arranque hasta que los otros dos nodos se hayan conectado al servidor GNBD, o si por ejemplo arrancamos centos02 y centos03, y centos01 todavía no está inicializado, esos dos nodos esperarán hasta que el servicio GNBD esté listo antes de lanzar el cliente.

La otra sección principal del fichero de configuración es la de los recursos. Se han definido tres recursos: un script de arranque y parada del cliente GNBD, otro script de arranque y parada para el servidor GNBD y un dispositivo (GFS2) que será montado en un directorio concreto (/mnt/gfs2_gnbd/).

A su vez se ha creado un dominio (failoverdomain) exclusivo para cada uno de los nodos. De esta forma podremos asociar posteriormente a cada uno de los dominios un determinado servicio (service), el cual iniciará y detendrá ciertos recursos (script ref, clusterfs, ...).

Así de esta forma el servicio service_centos02 hará que cuando se inicie automáticamente (autostart="1"), se lance sobre el nodo centos02 el script gnbd_client, y a continuación, se monte el recurso resource_gfs2_gnbd.

Para que el servicio GNBD (servidor) puede ser iniciado y detenido automáticamente por cman, dentro del directorio /etc/init.d/ crearemos un script denominado gnbd_server, al cual ya hemos hecho referencia en el fichero de configuración. Para ello haremos una copia del script sshd (con el objetivo de salvaguardar los contextos de SELinux) y lo cumplimentaremos con las líneas de código necesarias para gestionar el servidor GNBD.
[root@centos01 ~]# cp -a /etc/init.d/sshd /etc/init.d/gnbd_server

[root@centos01 ~]# vim /etc/init.d/gnbd_server
#!/bin/bash
#
# gnbd_server Startup script for the GNBD server
#
# chkconfig: - 23 77
# description: GNBD server

RETVAL=0

start()
{
echo -n $"Starting gnbd_server: "
modprobe gnbd
gnbd_serv
gnbd_export -d /dev/VolGroup01/LogVol00 -e gfs2_gnbd ; RETVAL=$?
echo
return $RETVAL
}

stop()
{
echo -n $"Stopping gnbd_server: "
gnbd_export -R
gnbd_serv -k ; RETVAL=$?
rmmod gnbd
echo
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
gnbd_export -l ; RETVAL=$?
;;
*)
echo $"Usage: service gnbd_server {start stop restart status}"
esac

exit $RETVAL

[root@centos01 ~]# chkconfig --add gnbd_server

Y ya por último, en los nodos centos02 y centos03 se importará automáticamente el volumen exportado por centos01, el cual estará accesible a través del dispositivo /dev/gnbd/gfs2_gnbd (cuando un dispositivo GNBD es importado, un dispositivo con el mismo nombre con el que fue exportado será creado en el directorio /dev/gnbd/).

Dicho dispositivo importado lo tendremos que montar en algún lugar. Para ello crearemos un directorio de montaje (/mnt/gfs2_gnbd).
[... ~]# mkdir /mnt/gfs2_gnbd

A continuación se muestra el script de arranque del cliente GNBD para los nodos centos02 y centos03.
[... ~]# cp -a /etc/init.d/sshd /etc/init.d/gnbd_client

[... ~]# vim /etc/init.d/gnbd_client
#!/bin/bash
#
# gnbd_client Startup script for the GNBD client
#
# chkconfig: - 25 75
# description: GNBD client

RETVAL=0

start()
{
echo -n $"Starting gnbd_client: "
modprobe gnbd ; sleep 3
gnbd_import -i centos01.local ; RETVAL=$?
echo
return $RETVAL
}

stop()
{
echo -n $"Stopping gnbd_client: "
gnbd_import -R ; RETVAL=$?
rmmod gnbd
echo
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
gnbd_import -l ; RETVAL=$?
;;
*)
echo $"Usage: gnbd_client {start stop restart status}"
esac

exit $RETVAL

[... ~]# chkconfig --add gnbd_client

Ahora sólo tendremos que reiniciar los demonios gfs2, cman, rgmanager y clvmd en cada uno de los nodos, y mediante el comando chkconfig haremos que dichos demonios se inicien automáticamente cada vez que arranque el nodo.
[... ~]# service gfs2 restart

[... ~]# service cman restart

[... ~]# service rgmanager restart

[... ~]# service clvmd restart


[... ~]# chkconfig gfs2 on

[... ~]# chkconfig cman on

[... ~]# chkconfig rgmanager on

[... ~]# chkconfig clvmd on

Si ejecutamos el comando clustat, podremos ver la configuración actual del cluster que acabamos de levantar. Por un lado se tiene la lista de miembros del cluster (Member Name) y por el otro, la lista de servicios definidos (Service Name), así como su propietario (Owner) y estado (State).
[root@centos01 ~]# clustat
Cluster Status for mycluster @ Tue Jul 28 16:12:55 2009
Member Status: Quorate

Member Name ID Status
------ ---- ---- ------
centos03.local 1 Online, rgmanager
centos02.local 2 Online, rgmanager
centos01.local 3 Online, Local, rgmanager

Service Name Owner (Last) State
------- ---- ----- ------ -----
service:service_centos01 centos01.local started
service:service_centos02 centos02.local started
service:service_centos03 centos03.local started

Si en un momento dado deseamos conocer el número de nodos asociados al sistema GFS2, podremos ejecutar el siguiente comando:
[root@centos02 ~]# gfs2_tool journals /mnt/gfs2_gnbd/
journal2 - 128MB
journal1 - 128MB
journal0 - 128MB
3 journal(s) found.

Jul 20, 2009

Repositorio local de paquetes RPM por HTTP

Muchas veces puede ser necesario instalar en nuestra red un repositorio local de paquetes, ya que si por ejemplo se tienen muchas máquinas y surge una actualización, todos los equipos realizarán la misma operación (descargar la actualización de Internet) consumiendo ancho de banda para la empresa.

Otro de los motivos para instalar un repositorio local es la rapidez, ya que al encontrarse el repositorio dentro de la propia LAN, el proceso de descarga e instalación será mucho más rápido que si se trabaja sobre un servidor remoto.

Y por último, también se gana en seguridad, ya que sólo una de las máquinas (la que contenga el repositorio local) será la que tenga que tener acceso a Internet para descargar las actualizaciones, evitando de esta forma que el resto de equipos (susceptibles de instalar paquetes) tengan que salir a Internet.

Las pruebas se van a hacer en una CentOS 5.3, y para ello se va a crear un repositorio local para esta misma distribución de 64 bits, el cual será ofrecido al resto de máquinas de la LAN a través de un servidor Apache.

Lo primero que vamos a hacer es crear la estructura de directorios dentro del servidor que hará las labores de repositorio (centos01, con dirección IP 192.168.1.10).
[root@centos01 ~]# mkdir -p /var/www/mirror/CentOS/5.3/os/x86_64/CentOS

[root@centos01 ~]# mkdir -p /var/www/mirror/CentOS/5.3/updates/x86_64/RPMS

El directorio os lo utilizaremos para almacenar los paquetes base del sistema operativo, es decir, los que vienen nada más liberarse la distribución.

Si se tiene habilitado SELinux, habrá que modificar las listas de control de acceso (ACLs) de los contextos de seguridad del directorio raíz.
[root@centos01 ~]# chcon -R -u system_u /var/www/mirror/

[root@centos01 ~]# chcon -R -t httpd_sys_content_t /var/www/mirror/

Y a nivel de firewall, habrá que añadir una regla para abrir el puerto 80 (HTTP).
[root@centos01 ~]# cat /etc/sysconfig/iptables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp --dport ssh -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp --dport http -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp -j ACCEPT
-A RH-Firewall-1-INPUT -j LOG
-A RH-Firewall-1-INPUT -j REJECT
COMMIT

El contenido del directorio os no cambiará nunca, así que lo que haremos será copiar en él los paquetes base desde un DVD.
[root@centos01 ~]# cp /media/CentOS_5.3_Final/CentOS/* /var/www/mirror/CentOS/5.3/os/x86_64/CentOS

Si se quiere comprobar la firma de los paquetes, ubicaremos la clave GPG en el directorio x86_64.
[root@centos01 ~]# ls /var/www/mirror/CentOS/5.3/os/x86_64/
RPM-GPG-KEY-CentOS-5 CentOS

A continuación tendremos que crear el directorio repodata asociado a dicho contenido base, el cual contendrá ficheros XML encargados de indexar los paquetes. Para ello necesitaremos tener instalado el paquete createrepo.
[root@centos01 ~]# yum install createrepo

[root@centos01 ~]# createrepo /var/www/mirror/CentOS/5.3/os/x86_64/

Las actualizaciones que vaya publicando CentOS las ubicaremos dentro del directorio updates. Este contenido deberá estar sincronizado con alguno de los repositorios de CentOS situados en Internet y que sean compatibles con rsync, ya que esta herramienta la utilizaremos para realizar dicha sincronización de forma periódica (definiremos una tarea en el cron para que se ejecute por ejemplo todos los días a la 01:05h - update_repo.sh).
[root@centos01 ~]# cat /etc/crontab
...
5 1 * * * /root/update_repo.sh

[root@centos01 ~]# cat /root/update_repo.sh
#!/bin/bash
rsync -at --delete rsync://mirrors.kernel.org/centos/5.3/updates/x86_64/RPMS/ /var/www/mirror/CentOS/5.3/updates/x86_64/RPMS/

if [ $(find /var/www/mirror/CentOS/5.3/updates/x86_64/RPMS/ -cmin -60 | wc -l) -gt 0 ]; then
createrepo /var/www/mirror/CentOS/5.3/updates/x86_64/
fi

[root@centos01 ~]# chmod +x /root/update_repo.sh

El script anterior lo que hace es sincronizar las actualizaciones disponibles para CentOS 5.3 en kernel.org, con nuestro directorio local, descargando únicamente los paquetes que hayan sido incorporados o modificados. A través de la línea if se comprobará si realmente ha habido alguna descarga, y en caso afirmativo, se volverá a generar nuevamente el directorio createrepo.

El siguiente paso será el de definir un virtual host para ofrecer ese contenido. También habrá que reiniciar Apache.
[root@centos01 ~]# cat /etc/httpd/conf.d/updates.conf
NameVirtualHost 192.168.1.10:80
<VirtualHost 192.168.1.10:80>
ServerName centos01
DocumentRoot /var/www/mirror
ErrorLog logs/updates-error_log
CustomLog logs/updates-acces_log combined
<Directory /var/www/mirror>
Options Indexes Includes
</Directory>
</VirtualHost>

[root@centos01 ~]# service httpd restart

Y ya por último, habrá que crear un fichero .repo en cada una de las máquinas que vayan a emplear el repositorio local. Para ello haremos una copia de un archivo ya existente (con el objetivo de salvaguardar los contextos de SELinux), lo borraremos y lo editaremos.
[root@centos02 ~]# cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Local.repo

[root@centos02 ~]# >/etc/yum.repos.d/CentOS-Local.repo

[root@centos02 ~]# vim /etc/yum.repos.d/CentOS-Local.repo
[base-local]
name=CentOS-$releasever - Base Local
baseurl=http://192.168.1.10/CentOS/5.3/os/$basearch/
enabled=1
gpgcheck=1
gpgkey=http://192.168.1.10/CentOS/5.3/os/$basearch/RPM-GPG-KEY-CentOS-5

[update-local]
name=CentOS-$releasever - Updates Local
baseurl=http://192.168.1.10/CentOS/5.3/updates/$basearch/
enabled=1
gpgcheck=1
gpgkey=http://192.168.1.10/CentOS/5.3/os/$basearch/RPM-GPG-KEY-CentOS-5

Jul 14, 2009

Liberar la memoria RAM cacheada en Linux

Existen numerosas aplicaciones que cachean datos en la memoria RAM, es decir, dejan información almacenada de forma permanente en este tipo de dispositivo.

Esta práctica puede llegar a ser contraproducente, ya que si un sistema se queda sin memoria RAM comienza a emplear memoria swap, situación que debería ser evitada en la mayoría de los casos.

A partir del kernel 2.6.16 se introdujo la posibilidad de actuar sobre esa información cacheada en la memoria RAM. Para ello se tiene un fichero denominado /proc/sys/vm/drop_caches que es utilizado por el kernel para saber qué debe hacer con esos datos en función del número que se escriba en dicho fichero:
  • 0: No hacer nada.
  • 1: Liberar la pagecache.
  • 2: Liberar inodos y dentries.
  • 3: Liberar pagecache, inodos y dentries.
La pagecache es la memoria caché de páginas. Los inodes es la representación que utiliza el sistema operativo para los ficheros y directorios guardados en memoria o disco (un inodo contiene todos los metadatos necesarios para administrar objetos en el sistema de ficheros, incluyendo las operaciones que sean posibles sobre él). Y por último, los dentries se utilizan para mantener la relación entre los directorios y los ficheros, así como para realizar la traducción entre los nombres y los inodos.

Por lo tanto, si quisiéramos liberar la pagecache, los inodos y los dentries ejecutaríamos el siguiente comando:
# sync ; echo 3 > /proc/sys/vm/drop_caches

Se recomienda ejecutar previamente el comando sync para forzar la grabación en la caché de aquellos datos que pudieran estar pendientes.

Jul 6, 2009

Optimización del kernel de Linux con sysctl

Los sistemas operativos pertenecientes a la familia GNU/Linux suelen traer configurado por defecto unos valores para los parámetros del kernel que no son los más adecuados, ya que en la mayoría de los casos éstos suelen ser muy dependientes de las características hardware y de los tipos de servicios que se quieren ofrecer; los valores que vienen por defecto no aprovechan al máximo las características de la máquina.

A través del comando sysctl pueden observarse todos los parámetros de configuración del kernel así como sus valores.
[root@centos ~]# sysctl -a
sunrpc.max_resvport = 1023
sunrpc.min_resvport = 665
sunrpc.tcp_slot_table_entries = 16
sunrpc.udp_slot_table_entries = 16
...

A continuación vamos a ver los parámetros más importantes que pueden afectar al rendimiento del sistema, así como sus valores más óptimos. Estas variables del kernel deben de ser configuradas dentro del fichero /etc/sysctl.conf. Una vez que hayamos editado el fichero, ejecutaremos el comando sysctl -p para aplicar los cambios y hacer que éstos sean persistentes después de un reinicio.
[root@centos ~]# cat /etc/sysctl.conf
...
# Buffer de envío de datos (valores mínimo, defecto y máximo - bytes)
net.ipv4.tcp_wmem = 8192 87380 16777216

# Buffer de recepción de datos (valores mínimo, defecto y máximo - bytes)
net.ipv4.tcp_rmem = 8192 87380 16777216

# Límite máximo para el buffer de envío de datos (bytes)
net.core.wmem_max = 16777216

# Límite máximo para el buffer de recepción de datos (bytes)
net.core.rmem_max = 16777216

# Rango de puertos locales que pueden ser empleados
net.ipv4.ip_local_port_range = 1024 65000

# Buffer para los paquetes SYN
net.ipv4.tcp_max_syn_backlog = 2048

# Tiempo que permanece el socket abierto al cerrar una conexión (sg)
net.ipv4.tcp_fin_timeout = 25

# Intervalo para comprobar que una conexión abierta pero no utilizada sigue viva (sg)
net.ipv4.tcp_keepalive_time = 1200

# Número máximo de archivos que el kernel podrá asignar
fs.file-max = 407020

# Límite de empleo de memoria física a partir del cual se recurrirá a la swap
vm.swappiness=10
...


[root@centos ~]# sysctl -p

Con respecto al parámetro fs.file-max, su valor por defecto suele ser un 10% de la cantidad de memoria RAM en KB. Se puede optimizar empleando un 20%.

Por último, vamos a detenernos en uno de las opciones más importantes de cara a la configuración del comportamiento del kernel: vm.swappiness. Este valor se corresponde a un porcentaje comprendido entre 0 y 100, y representa el momento a partir del cual el sistema comenzará a utilizar memoria swap.

Por ejemplo, el valor que viene por defecto es 60, lo que significa que cuando el uso de la memoria física alcance un 40% (sin tener en cuenta la cacheada), se comenzará a utilizar el área swap.

Que un sistema operativo utilice la memoria swap es totalmente contraproducente, ya que esta memoria es un espacio reservado en el disco duro y como tal, los accesos serán muchos más lentos en comparación con la memoria RAM, con lo que el rendimiento general del sistema podrá verse seriamente deteriorado.

Jul 1, 2009

Copias de seguridad con rsync

Rsync es una herramienta muy utilizada en el mundo Linux para hacer copias de seguridad o backups, tanto de ficheros como de directorios.

Una de las principales ventajas de esta aplicación es que permite realizar copias incrementales: cada uno de los ficheros sobre los que se aplica un backup es dividido por rsync en diferentes bloques, obteniendo de cada uno de ellos una suma. Este checksum agilizará enormemente las ejecuciones de rsync, ya que cuando tenga que hacer un backup por segunda vez sobre un mismo conjunto de archivos, lo que hará será comprobar las sumas de los diferentes bloques (operación muy rápida en tiempos de cómputo), y aquellos bloques de datos cuyo checksum no coincida serán los que realmente se copien, es decir, realizará una copia de seguridad por incrementos.

Vamos a suponer que se quiere hacer un backup de todo el directorio de configuración de Apache y depositarlo en /backup/ (las pruebas se realizarán sobre una distribución CentOS 5.3).
# tree /etc/httpd/
/etc/httpd/
|-- conf
| |-- httpd.conf
| `-- magic
|-- conf.d
| |-- README
| |-- logserver.conf
| |-- proxy_ajp.conf
| `-- welcome.conf
|-- logs -> ../../var/log/httpd
|-- modules -> ../../usr/lib64/httpd/modules
`-- run -> ../../var/run

5 directories, 6 files

Para realizar la copia de seguridad se ejecutará rsync con las siguientes opciones:
  • -a, --archive: aplicar recursión a los directorios y conservar la mayoría de los permisos.
  • -l, --links: conservar los enlaces simbólicos de los archivos en el destino.
  • -t, --times: conservar la fecha de los archivos en el destino.
  • -g, --group: conservar el grupo de los archivos en el destino.
  • -v, --verbose: incrementar la información mostrada por pantalla durante la transferencia.
  • -b, --backup: realizar copias de seguridad incrementales.
  • --no-whole-file: no copiar el fichero entero. Para archivos locales, rsync usa por defecto la opción -W (--whole-file), ya que considera que los recursos empleados para calcular la diferencia son mucho mayores que el hecho de copiar el fichero entero.
Otra opción bastante interesante es --delete, que borra aquellos ficheros ya existentes en el destino pero que no se encuentren en el origen.
# rsync -altgvb /etc/httpd/ /backup/
building file list ... done
logs -> ../../var/log/httpd
modules -> ../../usr/lib64/httpd/modules
run -> ../../var/run
conf.d/
conf.d/README
conf.d/logserver.conf
conf.d/proxy_ajp.conf
conf.d/welcome.conf
conf/
conf/httpd.conf
conf/magic

sent 49565 bytes received 182 bytes 99494.00 bytes/sec
total size is 48979 speedup is 0.98

Como puede observarse en la salida anterior, se han copiado un total de 49565 bytes.

Ahora añadiremos cuatro caracteres al fichero httpd.conf y a continuación volveremos a aplicar la copia de seguridad:
# echo "abcd" >> /etc/httpd/conf/httpd.conf

# rsync -altgvb --no-whole-file /etc/httpd/ /backup/
building file list ... done
conf/httpd.conf

sent 617 bytes received 342 bytes 1918.00 bytes/sec
total size is 48984 speedup is 51.08

Puede observarse que no se han enviado todos los archivos, sino simplemente el bloque o incremento que se ha visto afectado: 617 bytes.

Al realizar las copias hay que tener en cuenta si el directorio origen se finaliza o no con la barra:
# rsync -altgvb --no-whole-file /etc/httpd /backup/
# rsync -altgvb --no-whole-file /etc/httpd/ /backup/

La primera opción copia el directorio httpd y la segunda el contenido del directorio httpd.

Y ya por último, decir que tenemos la posibilidad de hacer backups en una máquina remota:
# rsync -altgvb --no-whole-file /etc/httpd root@192.168.1.20:/backup/

Para que el comando anterior no nos pida la clave cada vez que se ejecute, es conveniente configurar el cliente y el servidor SSH implicados a través de claves RSA.