Ejecutando shell script en AWS Lambda

Llevo un tiempo dándole vueltas a migrar de mi servidor virtual privado hacia el cloud, en concreto hacia AWS, pero uno de los motivos que más me echan para atrás es todos los scripts, la mayor parte en shell script, que tengo programados para ejecutarse diariamente en mi servidor y que realizan tareas de lo más útiles. De todos ellos destacaría el que tengo para que cada día me “recolecte” el libro electrónico gratuito que publica Packtpub. Pues bien, parece que este impedimento ha llegado a su fin, ya que utilizando un pequeño truco se pueden ejecutar shell scripts en Lambda.
A continuación, os explico cómo he migrado mis shell scripts a Lambda.
Si habéis trabajado un poco con Lambda ya sabréis que los lenguajes que admite son C#, Java 8, Edge Node y Python, pero en ningún caso permite la ejecución de shell script. Entonces, ¿cómo vamos a ejecutar nuestros scripts?
Pues es bien sencillo, si no conocéis cómo funciona AWS Lambda os diré que se basa en tecnología de contenedores, esto significa que el proceso cree que está corriendo en un servidor Linux de manera totalmente aislada, por tanto nada nos impide hacer llamadas al sistema operativo y ejecutar comandos como ls, cd, cp, etc… y como alguno de vosotros ya habrá deducido tampoco nos impide ejecutar ficheros .sh.
La última parte que nos quedaría es ver cómo realizamos la subida de dichos ficheros, ya que no existe ningún mecanismo estándar de transferencia (ftp, sftp, etc…). Subiremos los ficheros junto los ficheros que contenga el código de la aplicación.
Os voy a relatar cómo he realizado la instalación del script que cada día se conecta a Packtpub y “compra” el libro gratuito. El código lo podéis localizar en este repositorio de Github (importante: tendríais que adaptar el fichero .sh con vuestras credenciales de Packtpub, es decir, con vuestro email y contraseña)
Dejadme que os cuente, a modo de guía paso a paso, cómo ejecutar scripts de manera planificada, emulando lo que haríamos editando el crontab de nuestro servidor Linux.
-
Lo primero que haremos será descargar los ficheros del repositorio de Github que básicamente son:
1.- El fichero .py que se encagará de ejecutar la llamada a sistema lanzado un shell para cargar el fichero .sh
from __future__ import print_function
import commands
def lambda_handler(event, context):
if commands.getstatusoutput('sh ./packtpub.sh')[0] == 0 :
return "Ok, enjoy your free book"
2.- El fichero .sh que ejecutará un curl en el contenedor donde se ejecute el código. Dicho curl ya está preparada para hacer login con las credenciales que indiquemos (email y contraseña), buscará el enlace del libro gratuito y simulará un click sobre dicho enalce.
rm /tmp/user.cookie; curl -b /tmp/user.cookie https://www.packtpub.com$(curl -L -k -d 'email=your%40email.com&password=yourpassword&op=Login&form_build_id=form-29b891c23331f6a85f502eef8b133303&form_id=packt_user_login_form' -b /tmp/user.cookie -c /tmp/user.cookie 'https://www.packtpub.com/packt/offers/free-learning' | grep -i 'freelearning-claim' | awk '{print $2}' | cut -d'"' -f2)
Es importante adaptar el fichero .sh con las credenciales correctas para que todo funcione. Una vez hecho esto generaremos un .zip que contenga los dos ficheros, el .py y el .sh.
- Nos conectaremos al panel de control de AWS y accederemos a la sección de Lambda:

- Pulsamos el botón “Get Started Now” y aparecerá una pantalla para seleccionar plantilla. seleccionamos “Blank Function”:

- En la pantalla de configuración de Triggers hacemos click sobre el recuadro con el contorno discontinuo y seleccionamos el trigger “CloudWatch Events - Schedule”:

- En el apartado de configuración seleccionamos que solo se ejecute una vez al día:
- En el apartado “Rule Name” indicamos una vez al día.
- La descripción la dejamos por defecto.
- Confirmamos que la expresión de planificación es rate(1 day)
- Por último, seleccionamos la casilla de “Enable trigger” para activar la regla.

- En la siguiente pantalla configuraremos el entorno de ejecución de nuestra función:
- En el campo nombre insertaremos un nombre identificativo de la función.
- La descripción que creamos apropiada.
- Y en el campo “Runtime” seleccionaremos Python 2.7.
- Como “Code entry type” indicamos “Upload a .ZIP file” y subiremos el fichero .zip generado en el primer punto.

- En el apartado de “Lambda Function Handler” indicaremos lo siguiente:
- Insertaremos en el campo “Handler” el nombre del fichero .py más el nombre de la función que se tendrá que ejecutar. Si hemos seguido el procedimiento sin modificar ningún nombre de fichero tendríamos que indicar packtpub.lambda_handler .
- “Role”: Seleccionamos “Choose a existing role”.
- “Existing Role”: “service-role/lamda_crontab_rol”.
- En el apartado “Advenced settings” modificaremos el timeout a 5 segundos, ya que en ocasiones Packtpub tarda algo en responder y el timeout por defecto de 3 segundos se queda algo corto. Una vez hecha esta modificación podemos pulsar el botón de “Next”.

- Si todo ha funcionado correctamente tendríamos que ver una pantalla similar a esta:

- Pulsaremos el botón de “Test” para ver que funciona correctamente:
- Seleccionamos “Scheduled Event”
- Y pulsamos “Save and Test”

- Nos tendría que aparecer una pantalla similar a la que pongo a continuación con el mensaje “Ok, enjoy your free book”. Importante: Packtpub limita a un libro al día, por tanto, por muchas veces que lo ejecutemos sólo tendremos disponible en nuestra cuenta de Packtpub una copia del libro).

¡Enhorabuena! Ya tenéis funcionando en Lambda una tarea programada que se ejecuta cada día y lanza un shell script para “recolectar” de manera automática los libros gratuitos de Packtpub. Y por cierto, todo a coste 0, ya que el consumo de ejecutar estos procesos es tan bajo que lo cubre la capa gratuita de AWS.
Espero que os sea útil y lo extrapoléis a otros escenarios.