Convirtiendo un programa de Python en un servicio

Hace no mucho necesite que un programa en escrito en python se ejecutara en una Raspberry Pi al inicio, es decir, ni bien booteara el sistema operativo iniciara el programa.

La forma mas adecuada fue hacerlo por medio de systemctl definiendo algunos parámetros.

Por supuesto que el programa debe tener algún tipo de bucle que mantenga el hilo activo; de lo contrario se va a ejecutar una sola vez y concluirá.

Para los fines del ejemplo, voy a utilizar ServerHotKeys.py que escucha el puerto serie y si llega ciertos caracteres reproduce un archivo mp3.

Este programa lo pueden encontrar en el siguiente repositorio: https://github.com/gsampallo/hotkeys_server

El ejemplo lo realizo sobre una raspberry pi 3 con rasbian. El primer paso será clonar el repositorio:

git clone https://github.com/gsampallo/hotkeys_server

Nos quedara el proyecto en la ruta /home/pi/hotkeys_server.

El siguiente paso será crear un archivo bash, al cual llamaremos start.sh que ejecute el programa:

#!/bin/bash
cd /home/pi/hotkeys_server
python3 ServerHotKeys.py

Debemos dar permiso de ejecución sobre el archivo, lo hacemos con:

chmod +x start.sh

Luego debemos crear un archivo al que llamaremos ServerHotKeys.service, que contendrá las características del servicio, su contenido sera el siguiente:

[Unit]
Description=ServerHotKeys Service
After=multi-user.target
 
[Service]
Type=idle
ExecStart=bash /home/pi/hotkeys_server/start.sh
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=ServiceHotKeys

[Install]
WantedBy=multi-user.target

Luego debemos crear un nuevo archivo con la configuración, al cual llamaremos ServerHotKeys.conf que contendra lo siguiente:

if $programname=='ServiceHotKeys' then /home/pi/hotkeys_server/log/ServiceHotKeys.log & stop

De modo de ir almacenando en la carpeta log dentro de hotkeys_server los archivos de log del servicio; no olvidar de verificar que exista este directorio, en caso que no este crearlo.

Copiamos ambos archivos a la ruta correspondiente:

sudo cp ServiceHotKeys.service /lib/systemd/system/
sudo cp ServiceHotKeys.conf /etc/rsyslog.d/

Cambiamos los permisos sobre el service:

sudo chmod 644 /lib/systemd/system/ServiceHotKeys.service

Luego debemos recargar el demonio para que tome el nuevo servicio, habilitarlo y por ultimo iniciarlo para que quede corriendo.

sudo systemctl daemon-reload

sudo systemctl enable ServiceHotKeys.service
sudo systemctl restart rsyslog

sudo systemctl start ServiceHotKeys.service

De esta forma queda habilitado el servicio para que siempre se ejecute al iniciarse la Raspberry Pi.

Tener en cuenta que el programa que tome de ejemplo, utiliza el puerto serie de la pc y tiene algunas dependencias, por lo que puede que no funcione; pero es posible tomarlo como ejemplo y construir su propio servicio en base a este.

Estadísticas de sistemas de Raspberry Pi

En mi casa tengo una Raspberry Pi como servidor casero, cumple tareas de broker y también la utilizo para descargar algunos archivos cuando no quiero utilizar la pc; como aun no la tengo dentro de un gabinete, me interesa monitorear la temperatura de la Raspberry para asegurarme que no tenga problemas.

La forma mas sencilla que encontré es crear un canal en thingspeak donde enviar los datos para poder verlo desde cualquier parte, en el canal definí tres campos a utilizar, siempre puedo volver y agregar uno mas: temperatura, cpu y idle (este ultimo quizás no es el más útil).

Es posible agregar mas campos si fuera necesario.

Mediante un simple script en Python recolectamos los datos del sistema de la RPI y los enviamos a ThingSpeak.

Para tomar el valor de uso de la CPU del sistema utilizo un programa llamado iostat , se instala en la RPI con:

sudo apt-get install iostat

Afortunadamente iostat tiene un parámetro que permite que la salida del comando sea en formato JSON lo cual hace mucho mas sencillo, si en la terminal ejecutamos:

iotstat -c -o JSON

Para ejecutar instrucciones del sistema desde Python importamos la libreria subprocess y lo realizamos de la siguiente manera:

import subprocess
import json
import requests

p = subprocess.Popen(['iostat','-c','-o','JSON'], stdout=subprocess.PIPE,stderr=subprocess.PIPE)
out, err = p.communicate()

Será necesario procesar out para tomar solo los valores que nos interesa:

data = json.loads(out)

system = data['sysstat']['hosts'][0]['statistics'][0]['avg-cpu']['system']
idle = data['sysstat']['hosts'][0]['statistics'][0]['avg-cpu']['idle']

Para obtener la temperatura del sistema utilizamos otro comando:

vcgencmd measure_temp

De igual forma que para obtener los valores de cpu realizamos

p = subprocess.Popen(['vcgencmd', 'measure_temp'], stdout=subprocess.PIPE,stderr=subprocess.PIPE)
out, err = p.communicate()

temp = out[5:9]

Por ultimo realizamos un request a ThingSpeak con los datos de los campos y nuestro api key para que actualice el canal:

apiKey = "XXXXXXXXXXX" #Replace with your own
url = "https://api.thingspeak.com/update?api_key"+apiKey+"&field1="+str(temp)+"&field2="+str(system)+"&field3="+str(idle)
r = requests.get(url)
print r.status_code

En el siguiente link pueden encontrar el programa completo

Si ejecutamos el programa vamos a informar, pero necesitaríamos programarlo para que se realice de forma periódica, para ello creamos un script bash llamado stats.sh:

#!/bin/bash
python stats1.py

Damos permisos de ejecución al script con chmod +x stats.py y agregamos la tarea a cron utilizando crontab -e y la siguiente linea:

*/5 * * * 0-7 /home/pi/stats.sh

Esto va a reportar los datos cada 5 minutos, si queremos alterar la frecuencia simplemente modificamos los valores de cron (dejo un link donde se explica como utilizarlo en detalle).

De esta forma tendremos la estadística del sistema de nuestra RPI en ThingSpeak