Skip to main content

FTPBOT - Automatizando tareas en los directorios FTP

::INTRO y PROBLEMA::

El problema: Implementar un proceso automático que sea capaz de notificar y enviar por correo electrónico los archivos que se suban a un directorio particular mediante sesiones FTP. El proceso debe ser capáz de examinar el directorio particular (sin recursividad) al cual se han subido los archivos y obtener el tamaño de cada archivo contendio en éste y notificarlo via e-mail a los destinatarios de interés. Una vez completado el requerimiento anterior, el proceso debe ser capáz de enviar mediante un mensaje de correo electrónico, el archivo encontrado en el directorio particular y adjuntarlo como parte del mensaje. Enviado el archivo adjunto, el proceso deberá eliminar del directorio particular especificado, el archivo que se acaba de enviar.

 

::LA SOLUCION::

Inicialmente pensé en darle solución al requerimiento anterior codificando un script en perl o en php, para este último, apoyándome en class.phpmailer.php y class.smtp.php; componentes que una vez utilicé en un proyecto web y que me parecieron supremamente sencillos de utilizar para lo que tiene que ver con el envio de correo electrónico.

Finalmente se me acordé de la potencia del Shell de Linux que junto con programas como mutt me podrían resolver el problema. La solución final quedó así:

  • Hacer un Shell Script que lea consulte si hay sesiones FTP activas por el usuario que nos interesa.

  • Si hay alguna sesión activa, no haga nada, seguro estarán subiendo en ese instante algún archivo.

  • Si no hay ninguna sesión activa, examinar el directorio de interés particular y enviar cada archivo encontrado como archivo adjunto de un mensaje de correo electrónico; notificar mediante otro mensaje de correo su tamaño en bytes. Utlizando mutt, claro está.

  • Mediante cron automatizar la ejecución de FTPBOT cada 10 minutos.

 

::EL SCRIPT::

#!/bin/sh

################################################################
# NOMBRE: ftpbot                 	VERSION: 1.0
# 
# DESCRIPCION
#   FTPBOT es un programa (ShellScript) basado en la Shell Bash 
#   del sistema operativo Linux disenado para examinar el 
#   contenido de un directorio en particular (sin recursividad) 
#   en busca de archivos regulares puestos en el mediante una 
#   sesion FTP; enviar un mensaje de correo electronico notificando 
#   cada archivo encontrado y su tamano; finalmente entregar 
#   mediante un mensaje de correo electronico cada archivo 
#   encontrado en este directorio. Cada archivo encontrado en el 
#   directorio particular especificado es eliminado una vez se 
#   haya enviado.
#
# AUTOR 
#   Juan F. Munoz - Fernandez. juanmuno@gmail.com
#
# COPYRIGHT
#    Esta obra esta bajo una licencia Reconocimiento-CompartirIgual 
#    de Creative Commons. Para ver una copia de esta licencia, 
#    visite http://creativecommons.org/licenses/by-sa/2.0/ 
#    o envie una carta a Creative Commons, 559 Nathan Abbott Way, 
#    Stanford, California 94305, USA.
#
# FECHA: 30 ABRIL DE 2005
################################################################
     
###
# ORG_NAME
#   Define con propositos informativos en la linea "Asunto" de 
#   los mensajes de correo, el nombre de la Organizacion. El 
#   valor de esta variable debe estar entrecomillado.
#
#   Ejemplo:
#
#   ORG_NAME="DigiNet Ltda"
###
ORG_NAME="DigiNet Ltda"

###
# USUARIO
#   Define el nombre del usuario con el que se inician las 
#   sesiones FTP. Corresponde al nombre del usuario existente 
#   en el sistema para el cual se desea que ftpbot actue. 
#   El valor de esta variable debe ir entrecomillado.
#
#   Ejemplo:
#
#   USUARIO="juanmuno"
###
USUARIO="juanmuno"

###
# FTP_DAEMON
#   Define el nombre del demonio FTP que se visualiza con la salida
#   del comando "ps U $USUARIO". El valor de esta variable se utiliza
#   para determinar si hay una sesion FTP activa por el $USUARIO al
#   momento de la ejecucion de este Script. El valor de esta variable
#   debe ir entrecomillado y debe ser exactamente igual a la salida
#   del comando anteriormente mencionado indicado en la columna COMMAND.
#   Por defecto, el valor de esta variable es [vsftpd] para el
#   demonio de Very Secure FTP. Si usted ejecuta otro demonio FTP,
#   asigne a esta variable el correspondiente valor.
#
#   Ejemplo de la salida del comando ps U $USUARIO:
#
#   ps U juanmuno
#
#       PID TTY      STAT   TIME COMMAND
#      4023 ?        S      0:00 [vsftpd]
#
#   Note como la columna COMMAND a la salida del comando ps,
#   nos informa el nombre del demonio que esta ejecucion por el
#   usuario juanmuno.
###
FTP_DAEMON="vsftpd"

###
# FTP_UPLOAD_DIR
#   Define el directorio del $USUARIO que inicia las sesiones FTP. 
#   Generalmente el valor de esta variable corresponde al home 
#   directory del $USUARIO que inicia las sesiones FTP.  
#   Es este directorio el que se examina para notificar y enviar 
#   los archivos encontrados en el. El valor de esta variable debe 
#   ir entrecomillado.
#
#   Ejemplo:
#
#   FTP_UPLOAD_DIR="/home/juanmuno"
#
#   Tambien puede especificarse de la siguiente manera:
#
#   FTP_UPLOAD_DIR="/home/$USUARIO"
#
#   En este ultimo caso, la variable $USUARIO definida anteriormente 
#   contendra el valor para completar la ruta al directorio de 
#   interes
###
FTP_UPLOAD_DIR="/home/$USUARIO"

###
# DESTINATION_MAIL
#   Define el buzon de correo al cual se enviara(n) el(los) 
#   archivo(s)   encontrado(s) en el directorio especificado por 
#   $FTP_UPLOAD_DIR. El valor de esta variable debe ir entrecomillado.
#
#   Ejemplo:
#   
#   DESTINATION_MAIL="juanmuno@diginet.com.co"
#
#   Si desea especificar mas de un buzon de correo para enviar los 
#   archivos, debera asignarlos a esta variable, especificando un 
#   espacio sencillo entre cada uno.
#
#   Ejemplo:
# 
#   DESTINATION_MAIL="juanmuno@diginet.com.co juanmuno@gmail.com"
###
DESTINATION_MAIL="juanmuno@diginet.com.co"

###
# DESTINATION_SUBJECT
#   Define el texto de la linea "Asunto" del mensaje de correo 
#   que adjunta el archivo colocado en directorio especificado 
#   por $FTP_UPLOAD_DIR. 
#
#   Ejemplo:
#
#   DESTINATION_SUBJECT="FTPBOT FTP - $ORG_NAME Adjunto archivo recibido"
###
DESTINATION_SUBJECT="FTPBOT FTP - $ORG_NAME Adjunto archivo recibido"

###
# NOTIFICATION_MAIL
#   Define el buzon de correo al cual se enviara la notificacion de que 
#   los archivos encontrados en $FTP_UPLOAD_DIR se han recibido exitosamente. 
#   Por defecto, tambien se envia notificacion al buzon esdpecificado 
#   por $DESTINATION_MAIL.
#   Asigne a esta variable la direccion de correo electronico de 
#   quien remotamente sube los archivos al servidor FTP y espera 
#   una notificacion de recepcion. El valor de esta variable debe ir 
#   entrecomillado.
#
#   Ejemplo:
#
#   NOTIFICATION_MAIL="pepito@foo.com"
#	
#
#   Si desea especificar mas de un buzon de correo para enviar los
#   archivos, debera asignarlos a esta variable, especificando un
#   espacio sencillo entre cada uno.
#
#   Ejemplo:
#
#   NOTIFICATION_MAIL="pepito@foo.com otro@foo.com"
###
NOTIFICATION_MAIL="juanmuno@diginet.com.co"

###
# NOTIFICATION_SUBJECT
#   Define el texto de la lía "Asunto" del mensaje de 
#   correo que se utiliza para enviar las notificaciones.
#
#   Ejemplo:
#
#   NOTIFICATION_SUBJECT="FTPBOT FTP - $ORGNAME Archivo recibido"
###
NOTIFICATION_SUBJECT="FTPBOT FTP - $ORGNAME Archivo recibido"


################ NO MODIFIQUE LAS LINEAS A CONTINUACION ####################

###
# Bloque de variables que define las rutas de los comandos
# utilizados al interior de este script. Defina las rutas de los
# comandos listados a continuacion y asignelos a cada una de las
# variables que llevan su mismo nombre.
#
# Lista de comandos:
# - mutt: Cliente de correo.
# - ps:   Reporta el estatus de los procesos en ejecucion.
# - grep: Imprime las lineas que corresponden con un patron
#         especificado.
# - cut:  Remueve/corta secciones espcificas de una linea.
# - ls:   Lista el contenido de un directorio.
# - rm:   Remueve archivos o directorios.
# - stat: Muestra la informacion de estado de un archivo o de
#         un FileSystem.
###
MUTT="/usr/bin/mutt"
PS="/bin/ps"
GREP="/bin/grep"
CUT="/bin/cut"
LS="/bin/ls"
RM="/bin/rm"
STAT="/usr/bin/stat"
MV="/bin/mv"
DATE="/bin/date"
TR="/usr/bin/tr"

###
# DIR_CONTENT
#   Define el nombre del archivo temporal en donde sera almacenada
#   la salida del comando "ls -1" realizada sobre el directorio
#   especificado por $FTP_UPLOAD_DIR
###
DIR_CONTENT=".DIR_CONTENT.TMP"

###
# BACKUP_DIR
#   Define el directorio en donde seran copiados los archivos que se
#   encontraron en $FTP_UPLOAD_DIR una vez hayan sido enviados.
###
BACKUP_DIR="/tmp"

###
# Consulto si el $USUARIO tiene algun proceso FTP en ejecucion
###
CURRENT_DAEMON=`$PS U $USUARIO | $GREP $FTP_DAEMON | $TR -s " " ";" | \
                $CUT -d ";" -f 4`
if [ $? ];
then
    ###
    # Si el usuario no tiene procesos FTP en ejecucion. Entro
    # a revisar el directorio FTP especificado por la variable
    # $FTP_UPLOAD_DIR
    ###
    if [ "$CURRENT_DAEMON" != "$FTP_DAEMON" ];
    then
	###
        # Creamos un archivo con el contenido del directorio $FTP_UPLOAD_DIR
        ###  
        $LS -1 $FTP_UPLOAD_DIR >> $DIR_CONTENT
	###
        # Pregunto si el archivo $DIR_CONTENT se creo exitosamente
        ###
        if [ -f $DIR_CONTENT ];
	then
            ###
            # Abro el archivo creado para leerlo linea a linea. El
            # numero 7 sera el descriptor para ese archivo
            ###
            exec 7< $DIR_CONTENT
            while :
            do
	        ###
                # Leo la linea y la almaceno en la vble $LINEA
                ###
                if read LINEA <&7 
                then
                   ###
                   # Pregunto si la vble $LINEA tiene algun contenido
                   ###
                   if [ -n "$LINEA" ];
                   then
                      ###
                      # Pregunto si el contenido de la vble $LINEA es un
                      # archivo regular
                      ###  
                      if [ -f $FTP_UPLOAD_DIR/"$LINEA" ];
                      then
                         ### 
                         # Consulto el tamano del archivo para enviar el
                         # mensaje de notificacion
                         ###
                         TAMANYO=`$STAT $FTP_UPLOAD_DIR/"$LINEA" | $GREP Size | 
                         $CUT -f 1 | $CUT -d : -f 2`
                         ###
                         # Envio el mensaje de notificacion
                         ###
                         echo -e "Se ha recibido el archivo: "$LINEA"\nTamano: $TAMANYO Bytes" | $MUTT -s "$NOTIFICATION_SUBJECT" $NOTIFICATION_MAIL $DESTINATION_MAIL
                         ###
                         # Envio el mensaje con el archivo adjunto
                         ##
                         echo "Adjunto viene el archivo recibido en el servidor FTP" | $MUTT -a $FTP_UPLOAD_DIR/"$LINEA" -s "$DESTINATION_SUBJECT" $DESTINATION_MAIL  
                         FECHA=`$DATE +%d%b%Y%H%M%S`
                         ###
                         # Hago copia de seguridad de lo que acabo de enviar
                         ###
                         $MV $FTP_UPLOAD_DIR/$LINEA $BACKUP_DIR/"$LINEA"."ftpbot".$FECHA
                      fi   
                   fi
                else
                   ###
                   # No hay mas lineas que leer. Termino de leer el archivo
                   # $DIR_CONTENT
                   ###
                   break
               fi
            done
            ###
            # Cierro el archivo abierto.
            ### 
            exec 7<&- 
	else
	    echo "Error al tratar de generar el archivo $DIR_CONTENT"
	fi
    else
        echo "En este momento hay sesiones activas en FTP por $USUARIO"
    fi	
else
    echo "Error encontrado en la ejecucion del comando $CURRENT_DAEMON"	
fi
$RM -rf $DIR_CONTENT

::MONTANDO EL CRON::

Para lograr que el anterior script se ejecute cada cierta frecuencia de tiempo, vamos a añadir una entrada al crontab de la siguiente manera:

  • Creamos un archivo con nuestro editor favorito:

    #vi miarchivo.cron
  • Agregamos la siguiente linea y guardamos el archivo:

    10,20,30,40,50 * * * * ftpbot
  • Ejecutamos el comando crontab y le pasamos como parámetro el nombre del archivo que acabamos de crear en el paso anterior

    # crontab miarchivo.cron

Con lo anterior, logramos que el script ftpbot se ejecute cada 10 minutos. Para una referencia detallada acerca del crontab, consulte man 5 crontab. Por lo pronto, si quisieramos que nuestro script se ejecutara cada 5 minutos, entonces creamos un archivo con la siguiente entrada:

5,10,15,20,25,20,35,40,45,50,55 * * * * ftpbot

Luego, le pasamos como parámetro al comando crontab el archivo con la entrada anterior:

# crontab miarchivo.cron

::MAN::

La pagina del manual para ftpbot se puede ver aqui

::FILES::

Clic aquí para descargar ftpbot.

Clic aquí para descargar la pagina del manual de ftpbot.

::REFERENCIAS::

Estas son algunas referencias las cuales consulté para llevar a buen término esta labor:

+ Teach Your Self Shell Programming in 24 Hours. SAMS PUBLISHING

+ PETERSEN, Richard. Fundamentos de programación en Linux. Osborne McGraw-Hill

+ R125: Unix Bourne Shell

+ Gopi Sundaram's comp.mail.pine FAQ Part 2

+ LinuxDevCenter.com: Command-Line Email

+ Advanced Bash-Scripting Guide

Licencia de Creative Commons
Esta obra está bajo una licencia de Creative Commons.