lunes, 29 de noviembre de 2021

Trucos para usar Cron como asistente de tareas.


 ¿Que es Cron y para que sirve?


Cron es una administrador de tareas de Linux que nos permitirá ejecutar comandos para por ejemplo realizar copias de seguridad, borrar archivos u otras tareas en un momento determinado. (cada hora, mes, en una fecha en concreto etc) y sin que nos tengamos que preocupar por ello. Es un demonio, un proceso que se ejecuta en segundo plano.

Cada usuario del sistema tiene lo que se llaman tablas de cron o "crontab". No es más que un archivo de texto, que posee una lista con todos los script o tareas a ejecutar. Podemos editarlas, verlas o incluso borrarlas. Además los usuarios podemos usar esas "crontab" para programar tareas. El programa "Cron" por si mismo, monitoriza automáticamente sus crontab y se asegura de cualquier trabajo que aparezca en un crontab se ejecute en el momento especificado.

Configurando Cron.


Podemos editar nuestro crontab particular usando el comando "crontab" junto con la opción -e (editar).  Si por defecto no tienes un editor predeterminado puedes establecerlo editando el archivo ~/.bashrc o incluso en el propio programa al ejecutar la orden. 

Yo voy a configurar el mío para que use "nano" y "gedit". La variable de entorno EDITOR establece que programa de edición usaremos cuando usemos el terminal, mientras que la variable VISUAL define que editor se usará en modo gráfico.

Abrimos el terminal y editamos el archivo ~/.bashrc

pi@raspberrypi:~ $ nano ~/.bashrc

y al final del mismo añadimos:

export EDITOR=nano
export VISUAL=gedit
Nota. He usado el editor nano como editor de terminal y gedit como editor en modo grafico, pero puedes usar el que más te guste.


Guardamos el archivo y refrescamos nuestra sesión de shell para que tenga en cuenta los nuevos cambios:

pi@raspberrypi:~ $ source ~/.bashrc
Ahora ya podemos editar o crear las "crontab" con nuestro editor preferido:


pi@raspberrypi:~ $ crontab -e
crontab -e


Programando una tarea.


El sistema cron funciona esencialmente como un calendario. Podemos decirle con que frecuencia queremos ejecutar un trabajo mediante el uso de cinco parámetros diferentes:

minuto, hora, día del mes, mes y día de la semana.

Los parámetros siguen este orden estricto, aunque veras que no es muy intuitivo. Para empezar, podemos pensar que el programa está configurado para ejecutar algo, siempre o cada x tiempo.



opciones de configuración de crontab



Veámoslo con un ejemplo. Si añadiésemos la siguiente entrada:


* * * * * touch /tmp/hola

Ejecutaríamos la orden touch /tmp/hola cada minuto, de cada hora, de cada día, durante todo el año. Vamos para siempre.

Lógicamente podemos restringir esto un poco, estableciendo valores a cada uno de los atributos. Por ejemplo para que la orden se ejecute en el minuto 30 podemos usar:

30 * * * * touch /tmp/hola

Podemos acotar un poco más añadiendo que se ejecute a una hora especifica (formato de 24 horas). Esta orden ejecuta el comando a las 3.30 am de cada día, todas las mañanas:

30 3 * * * touch /tmp/hola

También podemos hacer que se ejecute a esa hora pero solo los primeros días de cada mes:

30 3 1 * * touch /tmp/hola

Para poner el mes usaremos la forma numérica. El 1 para Enero, el 2 para febrero y así sucesivamente hasta el 12 para Diciembre. 

Lo mismo ocurre si queremos especificar los días de la semana, aunque tendremos que hacerlo en el orden anglosajón.  Es decir la semana comienza en Domingo y termina el Sábado. De esta forma el Domingo es el 0, el lunes el 1, el martes el 2, el miércoles el 3, el jueves el 4, el viernes el 5 y el sábado el 6.

Para verlo mejor. Si queremos que la tarea se ejecute a las 3 horas y 30 minutos durante el mes de abril pero sólo los lunes:

30 3 0 4 1 touch /tmp/hola

Usar Incrementos.


En todos los ejemplos anteriores hemos usado valores exactos. Pero también podemos usar cron para que ejecute una tarea pasado un periodo de tiempo. Por ejemplo podemos programar una tarea para que se repita cada 15 minutos, ojo ¡no en el minuto 15!

*/15 * * * * touch /tmp/hola
o podemos ejecutarla a las 10 de la mañana cada 3 días:

* 10 */3 * * touch /tmp/hola
o programarla para cada 6 horas:

* */6 * * * touch /tmp/hola

Formas abreviadas de Cron.


En las implementaciones más modernas de Cron también podemos usar una forma abreviada en lugar de la estructura que hemos visto anteriormente. Estas son:
  • @hourly - todas las horas durante su primer minuto = 0 * * * *
  • @daily - todos los dias a las 12 de la noche = 0 0 * * *
  • @weekly - todas las semanas, el primer minuto de la primera hora de las semana
             = 0 0 * * 0    
  • @monthly - todos los meses el primer dia = 0 0 1 * *
  • @yearly or @annually - se ejecuta una sola vez al año = 0 0 1 1 *
  • @reboot - se ejecuta una vez y nada más iniciarse el equipo.


Listar las tareas de Cron.


Usando la siguiente instrucción, podemos ver una lista con las tareas que tenemos en crontab.

$ crontab -l
15 3 * 4 1 touch /tmp/hello

Eliminar un Crontab.


Para eliminar un crontab  lo podemos hacer usando -r. Le podemos añadir también el parámetro -i para que sea interactivo es decir nos pregunte si estamos seguros de hacerlo.


crontab -r -i

Otras cosas sobre Cron.


- Cron es un demonio que ejecuta tareas, por lo que si en el momento de ejecutarlas el ordenador está apagado estas no se realizarán. Si queremos superar esta limitación podemos usar un programa llamado anacron que controlará si Cron ha ejecutado las tareas que tenía asignadas.

- Puede usar un generador en línea para crear el momento en que ejecutar la tarea. Por ejemplo Cron Job Generator te puede echar una mano.

- La tarea a ejecutar la puedes poner directamente, si es un comando sencillo. O puedes crear un script de bash con lo que quieras ejecutar (acuérdate de darle permisos de ejecución o no funcionará). Por ejemplo el siguiente script abre firefox en una ventana gráfica (Hay que poner un DISPLAY para abrir cualquier aplicación en un entorno gráfico):

tarea.sh 

#!/bin/bash

env DISPLAY=:0 firefox
todo los días a las 20:38 pm

crontab

38 20 * * * /home/pi/tarea.sh



lunes, 15 de noviembre de 2021

¿Como enviar emails a través del terminal en una Raspberry Pi?



imagen de entrada mostrando un correo



Enviando correos desde la terminal de bash de Rapsbian.

A veces crear un programa de Python para enviar correo electrónico, sobre todo la primera vez que lo haces, puede resultar un poco engorroso.  Por eso, resulta más útil tener configurado un servidor smtp que nos permita enviar correos directamente desde el terminal. Una vez que lo tenemos configurado, además de enviar emails desde la línea de comandos,  podremos incluso usar posteriormente Python para enviar mensajes.

En la Rapsberry Pi funciona bien el programa msmtp.

1.- Instalación.


pi@raspberrypi:~ $ sudo apt-get install msmtp

2.- Configuración.


Lo primero que tenemos que hacer es crear nuestro archivo de configuración del programa. En este ejemplo voy a usar una cuenta para trastear que tengo de gmail, pero puedes usar la de otro proveedor y te dará la configuración para tu cuenta. Tecleamos el siguiente comando:

pi@raspberrypi:~ $ msmtp --configure tuCuentaEmail@gmail.com
# - copy this to your configuration file /home/pi/.msmtprc
# - encrypt your password:
#   gpg -e -o ~/.msmtp-password.gpg
account tuCuentaEmail@gmail.com
host smtp.gmail.com
port 587
tls on
tls_starttls on
auth on
user tuCuentaEmail
passwordeval gpg --no-tty -q -d ~/.msmtp-password.gpg
from tuCuentaEmail@gmail.com

Como siempre al usar una cuenta de Gmail hay que tener en cuenta:

- Si usas una cuenta con un doble factor de autentificación, la cosa se complica ya que tienes que usar una contraseña única para la aplicación y usarla en el archivo de configuración de msmtp.  Se puede hacer, pero es más lioso, con lo que te recomiendo, mientras lo permita google, crear una cuenta sencilla sin doble factor de autentificación para trastear. Además en este último caso (si no usas un doble factor de autentificación) necesitas permitir el acceso de aplicaciones inseguras en tu cuenta. Lo puedes hacer en este enlace.

Volviendo a la configuración, el comando previo nos da lo que tenemos que escribir en el archivo de configuración. ¡Pero no nos crea el archivo! así que tenemos que hacerlo nosotros.

En nuestro directorio home creamos el fichero ~/.msmtprc

pi@raspberrypi:~ $ nano .msmtprc
! NOTA. No debemos utilizar 'sudo' ya que es el usuario, pi, en mi caso el que envía el correo.

Como yo solo voy a usar esta cuenta de gmail, en la cuarta línea del archivo de configuración, cambio 'account tuCuentaEmail@gmailc.om' por 'account default' ya que no voy a usar más correos y esta va a ser la cuenta por defecto.

.msmtp   

# - copy this to your configuration file /home/pi/.msmtprc
# - encrypt your password:
#   gpg -e -o ~/.msmtp-password.gpg
account default
host smtp.gmail.com
port 587
tls on
tls_starttls on
auth on
user tuCuentaEmail
passwordeval gpg --no-tty -q -d ~/.msmtp-password.gpg
from tuCuentaEmail@gmail.com
Si quieres ver como sería un archivo de configuración con múltiples cuentas de correo puedes acceder a este enlace de x86blog donde encontrarás más información.

En este punto casi estamos listos para enviar nuestro primer correo pero antes de eso debemos ejecutar:

pi@raspberrypi:~ $ chmod 600 .msmtprc

Esto lo hacemos por dos buenos motivos. El primero es para una mayor seguridad, ya que el archivo puede contener la contraseña en forma de texto plano y este comando hace que solo el usuario pi pueda leer y escribir este archivo. Y la segunda es porque si no lo hacemos msmtp nos dará un error “must have no more than user read/write permissions”

Ahora probamos si todo esta bien enviando el primer mensaje. Para ello vamos a comentar la línea "#passwordeval gpg --no-tty -q -d ~/.msmtp-password.gpg". Al no tener esta línea, el programa, al ejecutarse, nos va a preguntar por nuestra password, la cual tendremos que escribir. Esto no es muy seguro, pero para ver si hasta ahora vamos bien nos vale. En el próximo paso descomentaremos esta línea y usaremos nuestra contraseña automáticamente pero codificada, para que en caso de que alguien logre acceder a el archivo de configuración no la pueda ver. 

Después de comentar la línea, escribimos:

pi@raspberrypi:~ $ echo "This is an email test." | msmtp -d correoDestino@outlook.com
Si todo ha ido como se espera, el programa te mostrará muchas líneas y te preguntará la contraseña de tu cuenta de correo. Una vez que se la pongas acabará de enviar el email.

Solo te queda ir a la cuenta donde lo hayas enviado y comprobar que está allí. Puede ocurrirte, como me paso a mi, que aparezca en la carpeta de spam, pero no pasa nada, le dices que no es spam y ya aparecerá desde entonces en la bandeja de entrada.

3.- Aumentar la seguridad.

Es sistema que hemos utilizado para enviar el correo no es muy práctico. Si tenemos un script automático no podemos estar delante para teclear la contraseña. Y mucho menos (aunque si pones una línea como 'password tuContraseña' en la configuración funcionaría)  guardar tu contraseña de correo en el archivo de configuración que al fin y al cabo es un archivo de texto plano. Todo esto lo hacemos directamente desde la rapsberry pi o desde una conexión vnc. (Por que a mi por lo menos si me conecto mediante ssh para la configuración me funciona a medias. Una vez configurado ya puedo mandar los correos de una forma normal.)

Para incrementar la seguridad podemos hacer dos cosas.

A) Usar gnome-keyring

Si ya tenemos Raspbian instalado en modo gráfico podemos utilizar esta opción para guardar nuestra contraseña de correo codificada y no tener que teclearla cada vez que mandemos un correo.

Es importante no tener el autologin activado al iniciar Rapsbian ya que si lo tenemos en automático la primera vez que enviemos un correo nos dirá que el "llavero estandar", donde se guarda la contraseña está bloqueado y tendremos que usar la contraseña del llavero para desbloquearla. Aunque solo la primera vez que lo utilicemos. Aunque se podría solucionar dejando la clave del llavero en blanco (y entonces no nos pediría desbloquearla) por seguridad no es recomendable. 

Empezamos instalando las librerías necesarias:

pi@raspberrypi:~ $ sudo apt-get install libsecret-tools
pi@raspberrypi:~ $ sudo apt-get install gnome-keyring

Pasamos a codificar la contraseña de gmail y guardarla en el llavero de contraseñas.

Tecleamos:

pi@raspberrypu:~ $ secret-tool store --label=msmtp host smtp.gmail.com service smtp user tuCuentaEmail

Aquí nos pedirá la contraseña de gmail. La introducimos y después de darle al enter, nos saldrá esta ventana:

introducir clave para el gestor de contraseñas

Para que funcione todo bien, utilizamos de contraseña, la misma que tengamos para el usuario 'pi' o tu usuario en el comienzo de sesión. Así cuando nos registremos para acceder a la raspberry con el usuario pi o el que tú uses, automáticamente se desbloqueara el llavero de contraseñas y no tendremos que introducirla cada vez que mandemos un email.

Si queremos comprobar que hemos tecleado la contraseña correctamente usamos la instrucción:

pi@raspberrypi:~ $ secret-tool lookup host smtp.gmail.com
y nos devolverá el valor de la contraseña.

También lo podríamos gestionar visualmente en Raspbian pero tendríamos que instalar el paquete "seahorse"  que es una aplicación gráfica de Gnome para gestionar las contraseñas.

Ahora modificamos el archivo de configuración de msmtp para decirle de donde debe obtener la contraseña. Descomentamos la línea de la contraseña y ponemos la que aparece en negrita.

.msmtprc

account default
host smtp.gmail.com
port 587
tls on
tls_starttls on
auth on
user tuCuentaEmail
passwordeval secret-tool lookup host smtp.gmail.com
from tuCuentaEmail@gmail.com

Procedemos a reiniciar la rapsberry pi y nos aseguramos de no logearnos automáticamente, sino tecleando la contraseña.  (si tienes el logueo automático puedes cambiarlo con sudo raspi-config en opciones de inicio)

Cuando arranque de nuevo, intentamos enviar un email cualquiera y nos saldrá que aun, la contraseña del llavero está bloqueada y se necesita autentificación. Si queremos que se desbloquee al inicio de la sesión, dejamos la opción marcada "Desbloquear este depósito de claves automáticamente siempre que hay iniciado sesión" e introducimos de nuevo la contraseña que pusimos. (la que pusimos antes y recuerda que tuvo que ser la misma que usa tu usuario para iniciar sesión)

desbloquear inicio de sesion


Y ya está. A partir de ahora no habrá que teclearla más y podremos enviar nuestros correos de forma automática.

B) Guardar la contraseña encriptada.


Para encriptar la clave del correo vamos a usar gpg que ya viene por defecto en Rapsbian.

(existe un paquete más moderno gpg2, pero voy a usar este aunque sea más antiguo porque ya viene por defecto).

Generaremos nuestras claves público-privadas:

pi@raspberrypi:~ $ gpg --gen-key
El programa solo nos pedirá un nombre de usuario y una dirección de correo electrónico que será nuestra id para operar con gpg.

Nombre y apellidos: tuCuentaEmail
Dirección de correo electrónico: tuCuentaEmail@gmail.com
Ha seleccionado este ID de usuario:
    "tuCuentaEmail <tuCuentaEmail@gmail.com>"
A continuación nos pedirá una contraseña para proteger la clave. (Haz el favor de guardarla bien que sino luego no podremos descifrar los archivos.) Una vez que han pasado unos segundos ya nos saldrá un mensaje en el que el programa nos comunica nuestra clave pública y que todo ha terminado correctamente.

Nos vamos en el sistema operativo de la raspberry pi al directorio /dev/shm. Este directorio tiene la particularidad de que reside en memoria, por lo que todo lo que hagamos en el se borrará al reiniciar el sistema.  Seguimos con estas instrucciones:

# Vamos al directorio /dev/shm
pi@raspberrypi:~ $ cd /dev/shm
pi@raspberrypi:/dev/shm $

# Creamos un directorio temporal y le asignamos permisos solo al usuario.
pi@raspberrypi:/dev/shm $ mkdir temporal
pi@raspberrypi:/dev/shm $ chmod 700 temporal
pi@raspberrypi:/dev/shm $ cd temporal

# Codificamos nuestra contraseña de gmail. Dentro de temporal tecleamos:
> gpg --encrypt --output=.msmtp-password.gpg --recipient=tuCuentaEmail@gmail.com - <<END
> LacontraseñademicorreoGmail
> END

EXPLICACIÓN DEL COMANDO ANTERIOR.

1) Primero tecleamos el comando y pulsamos Intro. Asegúrate de no olvidar el guión cerca del final, lo que haría que el comando gpg leyera la clave privada de codificación de la "entrada standar" de linux, con lo que dejamos la puerta abierta a que otro la pudiera leer. 

2) Luego en esa línea ponemos la contraseña de la cuenta de gmail y pulsamos Intro.

3) tecleamos END y pulsamo intro.

Y ya está, si ahora miramos el directorio veremos nuestro archivo con la contraseña codificada:

pi@raspberrypi:/dev/shm/temporal $ ls -a
.  ..  .msmtp-password.gpg

Para proteger este archivo, aunque está encriptado le damos solo permisos al usuario para trabajar con el:

pi@raspberrypi:~ $ chmod 600 .msmtp-password.gpg 
Ahora lo movemos al directorio donde se encuentra el archivo de configuración de msmtp.

pi@raspberrypi:/dev/shm $ mv .msmtp-password.gpg ~/

Importante. Tenemos que entrar en el archivo de configuración de msmtp y descomentar la línea que comentamos al principio para que nos quede así:

msmtprc

# - copy this to your configuration file /home/pi/.msmtprc
# - encrypt your password:
#   gpg -e -o ~/.msmtp-password.gpg
account default
host smtp.gmail.com
port 587
tls on
tls_starttls on
auth on
user tuCuentaEmail
passwordeval gpg --no-tty -q -d ~/.msmtp-password.gpg
from tuCuentaEmail@gmail.com

Sin embargo por alguna extraña razón (algun bug) si intentamos mandar ahora un correo este no funciona porque

pi@raspberrypi:~ $ echo "This is an email test." | msmtp -d correoDestino@outlook.com
ignoring system configuration file /etc/msmtprc: No existe el fichero o el directorio
loaded user configuration file /home/pi/.msmtprc
falling back to default account
gpg: descifrado fallido: No secret key
msmtp: cannot read output of 'gpg --no-tty -q -d ~/.msmtp-password.gpg'
¡dice que no puede leer la contraseña y sin ni siquiera preguntarnos por la clave de descifrado!. Es curioso porque la instrucción gpg --no-tty -q -d ~/.msmtp-password.gpg si funciona correctamente al ejecutarlo en el terminal pero no dentro del programa al usarlo con passwordeval. Para solucionarlo hay que hacer una pequeña modificación y solo funciona si estas trabajando con Raspbian en modo gráfico.

Instalamos el paquete pinentry-gtk-2


pi@raspberrypi:~ $ sudo apt-get install pinentry-gtk2

y luego tenemos que crear en el directorio .gnupg el archivo gpg-agent.conf (sino existe ya) y poner esta línea:

~/.gnupg/gpg-agent.conf

pinentry-program /usr/bin/pinentry-gtk-2


Y por fin si mandamos un correo con el comando que vimos al principio del post ya funciona y nos pide la contraseña para desencriptar. Lo bueno además es que esta contraseña queda codificada en cache y podemos seguir mandando correos sin tener que volverla a teclear mientras dure la sesión.




Ya para finalizar y si quieres enviar los correos de una forma más cómoda puedes utilizar el programa mail que se encuentra dentro del paquete mailutils. Se se integra bien con mmstp y permite trabajar de forma más cómoda para incluir objeto del mensaje, enviar archivos adjuntos etc.