martes, 21 de octubre de 2014

Instalación del driver de MongoDB en Python

Para desarrollar aplicaciones Python basadas en la base de datos MongoDB

, es necesario instalar PyMongo, el driver oficial para Python

Instalación en Linux

La forma más sencilla de instalar PyMongo es mediante el siguiente comando:

$ easy_install pymongo

Si no lo tienes, puede instalarlo mediante el siguiente comando:

sudo apt-get install python-setuptools

Otra forma de instalarlo es mediante el gestor de paquetes pip. Si no lo tienes instalado, puedes adquirirlo mediante el siguiente comando:

$ sudo apt-get install python-pip

A continuación instalamos el driver mediante el siguiente comando:

$ pip install pymongo

Instalación en Windows

Para Windows disponemos de instaladores estándar. Basta con descargar el archivo .exe del driver más reciente de:

https://pypi.python.org/pypi/pymongo/#downloads

Y lanzar el instalador.

Probando PyMongo

Nada mejor que un ejemplo práctico para comprobar el funcionamiento de PyMongo. Para ello, crearemos un fichero llamado demoMongoDB.py, con el siguiente código:

from pymongo import MongoClient

conexion = MongoClient('localhost', 27017)
basedatos = conexion.pruebas
coleccion = basedatos.pruebas

print "Num. documentos:", coleccion.count()

for doc in coleccion.find():
   print doc

En la primera línea importamos el driver pymongo y la clase MongoClient, la cual gestiona una conexión cliente a la base de datos. A continuación creamos una conexión a una base de datos MongoDB localizada en nuestra propia máquina (localhost) y en el puerto estándar (27017). Después, desde la conexión, abrimos la base de datos pruebas. Después, desde la base de datos abierta, abrimos la colección pruebas. A continuación, visualizamos el número de documentos que tiene la colección. Por último, visualizamos todos los documentos de la colección.

Más info:

Instalación del driver de MongoDB para PHP

Instalación en Linux

Antes de proceder a la instalación y configuración del driver de MongoDB en Linux, es necesario tener instalado antes pecl. Si no lo tienes instalado, utiliza el siguiente comando:

sudo apt-get install php5-dev php5-cli php-pear

Para utilizar MongoDB desde PHP, primero hay que descargar el driver correspondiente en la siguiente URL:

http://pecl.php.net/package/mongo

Una vez descargado, procedemos a descomprimir el archivo y a compilar y a instalar el driver mediante los siguientes comandos:

$ tar zxvf mongodb-mongodb-php-driver-.tar.gz
$ cd
$ phpize
$ ./configure
$ make all
$ sudo make install

Debería mostrar un mensaje como el siguiente:

Installing shared extensions: /usr/local/lib/php/extensions/no-debug-zts-20121212/

La instalación debería configurar el archivo php.ini, apuntando al archivo mongo.so a través del parámetro extensions. Para verificarlo, primero localizamos el archivo mongo.so mediante el siguiente comando:

$ sudo find / -name mongo.so

Ese archivo debería estar localizado en el directorio

/usr/local/lib/php/extensions/no-debug-zts-<fecha>

Para verificar si se ha configurado correctamente, ejecutaremos el siguiente comando:

$ php -i | grep extension_dir

El resultado debería ser similar al siguiente:

extension_dir => /usr/local/lib/php/extensions/no-debug-zts-20121212 => /usr/local/lib/php/extensions/no-debug-zts-20121212

Después, modificar el archivo php.ini y configurar el siguiente parámetro:

extension=mongo.so

Por último, reiniciar el servidor de Apache.

Instalación en Windows

La instalación en Windows es más sencilla. Lo primero que hay que hacer es descargar la última versión del driver en la siguiente URL:

https://s3.amazonaws.com/drivers.mongodb.org/php/index.html

A continuación, descomprimir el archivo descargado y copiar el archivo php_mongo.dll en el directorio de extensiones PHP, el cual, normalmente, se llama ext.

Después, modificar el archivo php.ini y añadir la siguiente línea:

extension=php_mongo.dll

Por último, reiniciar el servidor de Apache.

domingo, 19 de octubre de 2014

Fechas en MongoDB

MongoDB es una base de datos muy potente a la hora de utilizar valores de fecha. En este artículo analizaremos cómo gestionar correctamente las fechas y cómo encontrar los datos en base a fechas.

Agregar fechas

La forma más sencilla de insertar una fecha es la siguiente:

> db.coleccion.insert({"fecha" : new Date()})

El comando anterior agrega un nuevo documento a la colección, con un campo fecha que contendrá la fecha y hora actuales. Si listamos el contenido del documento, obtendremos un resultado como el siguiente:

> db.coleccion.find()

{ "_id" : ObjectId("5443e87e5894b090804c822e"), "fecha" : ISODate("2014-10-19T16:36:14.197Z") }

El tipo de dato ISODate contendrá la fecha en formato internacional (año-mes-día), seguido de la hora con precisión de milésimas de segundo.

Para agregar una fecha específica sin especificar la hora, se puede utilizar la función Date() con el siguiente formato:

> db.coleccion.insert({fecha: new Date("2014, 10, 21")})

Si queremos agregar una fecha y hora concretas, podemos utilizar el tipo ISODate() como función para especificar el valor:

> db.coleccion.insert({fecha: ISODate("2014-10-19T18:56:20.197Z")})

Búsqueda de fechas

Para hacer una búsqueda exacta (por fecha y hora), podemos utilizar el siguiente formato:

> db.coleccion.find({"fecha" : ISODate("2014-10-20T22:00:00Z")})

{ "_id" : ObjectId("5443f41b5894b090804c8234"), "fecha" : ISODate("2014-10-20T22:00:00Z") }

Si deseamos buscar todos los documentos a partir de una fecha específica:

> db.coleccion.find({"fecha" : {"$gt" : ISODate("2014-10-18T00:00:00")}})

También podemos utilizar la siguiente sintaxis:

> db.coleccion.find({"fecha" : {"$gt" : new Date("2014-10-18")}})

En ambos casos indicamos a la función find() (encontrar) que compare el campo "fecha" con el valor a buscar, que es un nuevo documento que contiene el operador "$gt" (greater than ó mayor que) y la fecha a partir de la cual debe hacer coincidir el resultado.

Los operadores condicionales utilizados por MongoDB para evaluar las condiciones de los valores a encontrar son los siguientes:

  • $gt: greater than (mayor que)
  • $gte: greater than or equal (mayor o igual que)
  • $lt: less than (menor que)
  • $lte: less than or equal (menor o igual que)
  • $ne: not equal (distinto de)
  • $in: in (dentro de(un array)
  • $nin: not in (no dentro de (un array))

Por ejemplo, si deseamos encontrar aquellos documentos que se encuentren entre dos fechas dadas:

> start = ISODate("2014-10-18T00:00:00Z")
ISODate("2014-10-18T00:00:00Z")
> end = ISODate("2014-10-20T00:00:00Z")
ISODate("2014-10-20T00:00:00Z")
> db.coleccion.find({"fecha" : {"$gte" : start, "$lte" : end}})

Al encadenar una lista de criterios a evaluar, por defecto asumirá que se aplica una operación lógica "$and". Lo anterior sería lo mismo que este comando:

> db.coleccion.find({"$and" : [{"fecha" : {"$gte" : start}}, {"fecha" : {"$lte" : end}}]})

Si queremos omitir el rango anterior utilizaríamos el operador lógico "$or":

> db.coleccion.find({"$or" : [{"fecha" : {"$lt" : start}}, {"fecha" : {"$gt" : end}}]})

Los operadores lógicos utilizados por MongoDB son los siguientes:

  • $and: Todas las condiciones del array se deben cumplir
  • $or: Se debe cumplir, al menos, una condición del array
  • $not: Invierte la condición.

Puede ocurrir que deseemos obtener documentos que se encuentren entre una lista de posibles coincidencias. Para ello, utilizaremos el operador condicional "$in", seguido de un array con la lista de valores a evaluar:

> db.coleccion.find({"fecha" : {"$in" : [ISODate("2014-10-20T22:00:00Z"), ISODate("2014-10-19T18:56:20.197Z"), ISODate("2014-10-15T18:56:20.197Z")]}})

En el caso de que quisiéramos cualquier documento excepto los que se encuentran en la lista, utilizaríamos el operador condicional "$nin".

Optimización de las búsquedas

Para que nuestras búsquedas sean mucho más rápidas y eficientes, necesitaríamos indexar la colección por el campo fecha:

> db.coleccion.ensureIndex({"fecha" : 1})
{
   "createdCollectionAutomatically" : false,
   "numIndexesBefore" : 1,
   "numIndexesAfter" : 2,
   "ok" : 1
}

El comando ensureIndex permite crear un índice en base a la lista de campos especificados. Con un valor 1, indicamos que el campo esté ordenado de alfabéticamente o de menor a mayor. Si el valor fuese -1, el orden sería a la inversa.

lunes, 13 de octubre de 2014

Cómo sincronizar el Calendario de Outlook en Android

Me ha costado bastante descubrir cómo sincronizar el calendario de Outlook en Android. Por más que buscas en la aplicación Outlook, no encontrarás en calendario por ninguna parte, si no, solamente, una opción de ajuste para realizar la sincronización. Es decir, sincroniza los datos pero no ofrece la herramienta de calendario.

Por deducción, entendí que la aplicación Outlook solamente hacía de puente para los datos entre el servidor de Outlook y otra aplicación que lo gestionase, como es el Calendario de Android. Sin embargo, cuando abres el Calendario de Android no ves las tareas del calendario de Outlook. Si vas a Ajustes, verás que en la parte izquierda está configurada tu cuenta de Gmail, pero no la de Outlook. Si vas a la opción Añadir Cuenta y eliges Outlook.com, te pedirá los datos de configuración de tu cuenta en Outlook (Hotmail/Exchange), pero al final te dirá que la cuenta ya existe y está duplicada, por lo que no te dejará añadir la cuenta.

Finalmente realicé las siguientes acciones para configurarlo de la forma correcta:

  1. Desinstalar Outlook en Android.
  2. Volver a instalar Outlook en Android, PERO SIN CONFIGURAR LA CUENTA.
  3. Acceder a Configuración de Android
  4. Seleccionar Cuentas y Sincronización
  5. Seleccionar AGREGAR CUENTA
  6. Seleccionar Outlook.com
  7. Configurar los datos de tu cuenta de Outlook
  8. Al final aparecerá la cuenta en la lista de Cuentas y Sincronización.
  9. Seleccionar esta cuenta. Aparecerán su opciones de configuración
  10. Comprobar que están activadas las opciones Sincronizar Calendario y Sincronizar Contactos
  11. Acceder a la herramienta Calendario de Android
  12. Ir a Ajustes
  13. Comprobar que en la parte izquierda se ha añadido la cuenta de Outlook

martes, 7 de octubre de 2014

Automatizar Samba mediante scripts

Una de las facetas más útiles e importantes es poder realizar copias de nuestros archivos en repositorios remotos Samba. Pero lo más interesante es hacerlo de forma automática, sin una intervención humana. Esto toma gran relevancia a la hora de gestionar backups o copias de seguridad.

Mediante la herramienta smbclient podemos conectar remotamente con Samba, ofreciéndonos una consola de comandos especial para lanzar los comandos específicos de Samba. Pero esto, obviamente, requiere una sesión Samba y una interacción con el usuario para cada comando. Y lo que necesitamos es realizar de forma automática todas estas tareas.

Lo primero que tenemos que hacer es lanzar smbclient para que se conecte de forma automática a través de un fichero de configuración que contiene los datos de conexión. Normalmente, este fichero se llama .smbclient, a fin de tener una coherencia de nombre y porque dicho fichero aparece oculto. Este fichero ha de contener la siguiente configuración:

username=usuario_samba
password=contraseña
domain=grupo_trabajo

Para que smbclient se conecte al repositorio de Samba de forma automática, debe indicarse el fichero de configuración de la siguiente manera:

sudo smbclient //SERVIDOR/repositorio -A .smbclient

donde "SERVIDOR" será la IP o el nombre del servidor en donde está Samba, y "repositorio" será el nombre del repositorio al que se quiere acceder.

Ahora viene lo más interesante: ejecutar la secuencia de comandos de smbclient sin intervención humana. Esto se consigue si añadimos el parámetro -c seguido de una cadena de texto con la secuencia de comandos smbclient, separados con punto y coma (;).

sudo smbclient //SERVIDOR/repositorio -A .smbclient -c "comando1; comando2; ..."

He aquí un ejemplo:

sudo smbclient //192.168.98.200/mirepositorio -A .smbclient -c "cd Backups/LDAP; lcd /home/miusuario/backups/ldap; recurse; prompt; mput *; exit;"

Los comandos más utilizados de smbclient son los siguientes:

  • cd: Cambia de directorio en el repositorio Samba
  • lcd: Cambia de directorio local (en nuestra máquina)
  • ls [máscara]: Muestra el contenido del directorio actual (en Samba)
  • mget [máscara]: Descarga desde directorio actual en Samba, los archivos que coincidan con la máscara, y los aloja en el directorio actual en local.
  • mput [máscara]: Sube desde el directorio actual en local, los archivos que coincidan con la máscara, y los aloja en el directorio actual en Samba.
  • recurse: Realiza la transferencia de archivos mget/mput de forma recursiva.
  • prompt: Omite la confirmación de cada operación en cada fichero.
  • exit: Abandona smbclient.
  • help [comando]: Muestra la ayuda.

Exportar e importar datos en LDAP

Os paso un par de comandos muy útiles para realizar backups de un LDAP.

Para exportar todos los datos de LDAP en un archivo plano:

slapcat -l /ruta/archivobackup.ldif

Para importar los datos del fichero a LDAP:

slapadd -c -l backup.ldif

Usar comando sudo sin contraseña

El comando sudo de Unix es muy útil, ya que permite ejecutar comandos de nivel de administración como si fuéramos un superusuario. Para la ejecución del comando nos solicitará la contraseña de superusuario o de algún usuario definido en el fichero /etc/sudoers, el cual define qué usuarios pueden lanzar comandos sudo.

Cuando definimos scripts, el comando sudo puede suponer un inconveniente, especialmente cuando pretendemos automatizar tareas, tales como backups, ya que precisa de una intervención del usuario para introducir la contraseña.

Para llevar a cabo esta clase de tareas sin que se requiera la contraseña de superusuario, debemos realizar modificaciones en el fichero /etc/sudoers. Pero esto no se puede hacer directamente, ya que tiene permisos de sólo lectura. Para ello, debemos ejecutar el siguiente comando:

sudo visudo

La herramienta visudo está concebida especialmente para editar con seguridad el fichero /etc/sudoers, permitiendo, además, verificar la sintaxis y los errores.

Dentro del fichero /etc/sudoers podemos definir un grupo de programas autorizados y prohibidos a ejecutar con sudo, mediante la directiva Cmnd_Alias:

Cmnd_Alias AUTORIZADO = /ruta/programa1, /ruta/programa2
Cmnd Alias PROHIBIDO = !/ruta/programa1, !/ruta/programa2
usuario ALL = (ALL) AUTORIZADO
usuario ALL = PROHIBIDO

En realidad, podemos definir en un mismo grupo los programas permitidos y prohibidos. La diferencia entre ambos estaría en que los programas prohibidos deben llevar como prefijo el signo de admiración (!).

Si deseamos asignar todos los permisos sudo a un usuario específico, podríamos utilizar, directamente, una línea como ésta:

usuario ALL = (ALL) ALL

Si deseamos que, además, no requiera de contraseña, se utilizaría la siguiente línea:

usuario ALL = (ALL) NOPASSWD: ALL

Obviamente, esto no sería muy recomendado por seguridad. Podría definirse esta política de seguridad únicamente a ciertos programas:

Cmnd_Alias AUTORIZADO = /ruta/programa1, /ruta/programa2
usuario ALL = (ALL) NOPASSWD: AUTORIZADO

El archivo /etc/sudoers tiene una gran capacidad de configuración, además de lo visto anteriormente. Podemos, por ejemplo, definir alias para usuarios, así como también grupos de usuarios. Para más información, se puede consultar la ayuda que ofrece Unix:

man 8 sudo
man 5 sudoers
man 8 visudo

lunes, 6 de octubre de 2014

Programar eventos en Linux con CRON

Linux (y otros sistemas operativos basados en UNIX) posee una poderosa herramienta que permite programar eventos. Gracias a ello, podremos configurar que, cada cierto tiempo, se lance algún comando o programa. Esto es realmente útil, para tareas periódicas, tales como backups o copias de seguridad, transferencia de datos de un sistema a otro, copia de ficheros entre programas, etc.

CRON es un administrador de procesos en segundo plano (o demonios), y se encarga de revisar, a cada minuto, la lista de tareas o procesos programados en el fichero crontab, el cual está ubicado en /etc/crontab. Dentro de este fichero podemos configurar el intervalo en el que se ejecutarán las tareas, automatizando éstas. Cuando CRON revisa crontab, comprueba si hay alguna tarea o proceso que ejecutar en ese momento.

Para editar el crontab, ejecutar el siguiente comando:

sudo crontab -e

Con esto, se abrirá el editor para modificar el crontab correspondiente al usuario actual.

Las líneas de este fichero tienen el siguiente formato:

m h dom mon dow [usuario] comando

donde:

  • m: (minute) Minuto (0 a 59)
  • h: (hour) Hora (0 a 23)
  • dom: (day of month) Día del mes (1 a 31)
  • mon: (month) Mes (1 a 12)
  • dow: (day of week) Día de la semana (0 (domingo) a 6 (sábado))
  • usuario: Nombre del usuario Unix que lanza la tarea
  • comando: Comando Unix que ejecuta la tarea

Los parámetros m, h, dom, mon y dow pueden tener valores especiales:

  • * : (asterisco) Cualquier valor
  • valor1[,valor2...] : (lista separada por comas) Cualquiera de los valores especificados en la lista

Ejemplos:

  • 30 * * * * root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) cada minuto 30, a todas horas, todos los días y todos los meses
  • 0 23 * * 1,3,5 echo "Se ha ejecutado":A las 23:00 horas los lunes(1), miércoles(3) y viernes(5)
  • 0 23 * * mon,wed,fri echo "Se ha ejecutado":A las 23:00 horas los lunes(mon), miércoles(wed) y viernes(fri)
  • 30 7 1 * * root /etc/backup/backup.sh:Lanza el script backup.sh a las 7:30 de día 1 de cada mes, cualquier día de la semana

Existen algunas plantillas que facilitan el uso de los parámetros de frecuencia:

  • @hourly root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) en el primer minuto de cada hora (0 * * * * ...)
  • @daily root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez al día, a las 00:00 horas (0 0 * * * ...)
  • @midnight root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez al día, a las 00:00 horas (0 0 * * * ...)
  • @weekly root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez a la semana (domingos, a las 00:00 horas) (0 0 * * 0 ...)
  • @monthly root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez al mes (día uno, a las 00:00 horas) (0 0 1 * * ...)
  • @yearly root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez a la año (día 1 de Enero, a las 00:00 horas) (0 0 1 1 * ...)
  • @annually root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez a la año (día 1 de Enero, a las 00:00 horas) (0 0 1 1 * ...)

Otros parámetros de crontab:

  • crontab -l: Muestra las tareas CRON del usuario actual
  • crontab -r: Elimina el crontab

Para ver el log de CRON:

sudo nano /var/log/syslog

Puede ocurrir que en el log aparezca un error como éste:

CRON[8380]: (CRON) info (No MTA installed, discarding output)>/p>

Esto se debe a que CRON necesita tener configurado un servidor de correo para las notificaciones. Por ello, será necesario instalar postfix

sudo apt-get install postfix

Otra forma de evitar estos mensajes es cambiar la salida de las notificaciones, añadiendo al final de cada tarea en crontab lo siguiente:

[tarea] >/dev/null 2>&1