martes, 13 de septiembre de 2022

Buenas practicas Shell Script

Ahí van un compendio de buenas prácticas, bastante sencillas de aplicar, pero que de no estar haciendolo ya, pueden marcar una gran diferencia en la calidad de tus scripts...

¿Que shebang?... #!/usr/bin/env bash  Vs #!/bin/bash

Si hablamos de flexibilidad es preferible usar #!/usr/bin/env bash , dado que no requiere que el sistema tenga bash en /bin, solo que este en el path del usuario, si por el contrario hablamos de seguridad, es preferible #!/bin/bash dado que un usuario no podría tener un bash distinto al del sistema.

Mejor opción larga... --output vs -o

Siempre que sea posible y por temas de mantenimiento de código, es preferible usar la opción más legible para la mayoría, por lo que usaremos la opción "larga"

Cabecera de control.

Como norma es recomendable proveer a nuestro script de ciertos controles o salvaguardas, para evitar comportamientos no deseados. Un buen punto de partida puede ser este aunque puede ajustarse según preferencias.

set -o errexit # abort on nonzero exitstatus
set -o nounset # abort on undeclared variable
set -o pipefail # don't hide errors within pipes
# set -o xtrace # track what is running - debugging

Con esto evitamos que el script siga ante:

  • errores de alguno de los comandos., si definimos esto en el shebang en caso de forzar la ejecución bash xxx.sh , no se aplicará, por lo que se recomienda usar set
  • variables no declaradas, salvo que se indique lo contrario explícitamente. (Más adelante)
  • Salida detallada de los errores

Con la ultima opcion podemos activar la traza de ejecución para debbugear errores.

Variables

  • Siempre debemos definir las variables como ${var} y no como $var
  • Las variables que pueden contener space: deben usar "", de modo que ${var} sería "${var}"
  • Usaremos "${var}" dentro de una comparación, para evitar errores de sintaxis con variables no definidas.
  • Variables globales de solo lectura con el comando readonly: readonly mivariable = "/opt/mipath/mifile.sh"

Capitalización:

  • Variables de entorno en mayúsculas (exportadas): ${ALL_CAPS}
  • Variables locales del script en minúsculas: ${lower_case}

Sustitución de comandos:

  • Usar $(command) antes que `command`

miércoles, 20 de mayo de 2020

Vuelta a los orígenes.

Después de 6 años, voy a abandonar el site que tenía contratado y volver al principio.

No quiero perder los pocos o muchos, según quien lea esto, posts que he subido estos años. Así que voy a ir cargándolos poco a poco, respetando las fechas de publicación, ya que la herramienta de importación no está funcionando todo lo bien que debería.

Es una lástima no poder mantener los comentarios, pero no veo manera de hacerlo.

La intención siempre es la misma, retomar las publicaciones, pero la realidad suele ser diferente, así que no me prometeré nada esta vez...

Si escribo.... genial¡ ... Si no lo hago.... será por algo xDDD

Nota: Ya están migradas todas las entradas

lunes, 20 de noviembre de 2017

Delete ElasticSearch – Recuperar espacio – forcemerge

Con el funcionamiento normal y con espacio disponible en disco, tras cada borrado, cuando se dispara el «merge» de los segmentos, se crean segmentos de mayor tamaño en los cuales ya no tenemos los datos eliminados.
Hasta este punto, los datos eliminados, no están disponibles para lucene, por lo que no podemos realizar búsquedas sobre ellos, pero sí están, en los segmentos que los tenían, por lo que el espacio en disco, no se ha liberado.
Este proceso puede ser lanzado automáticamente, cada intervalo de tiempo o cada número de mensajes, o puede ser lanzando manualmente usando la API.
Al lanzarlos manualmente:
 curl -XPOST 'localhost:9200/indice/_forcemerge'
Provocamos que se haga un merge de todos los segmentos, creando segmentos de mayor tamaño, en los que no están los datos eliminados.  Este proceso crea un segmento temporal, que ira creciendo hasta tener la totalidad de los datos, antes de realizar el borrado de los segmentos que lo forman y consolidarse… y es aquí donde tenemos el problema….
Si estamos demasiado justos de espacio en disco, no tendremos espacio suficiente para crear este nuevo segmento, y por consiguiente, no podremos liberar el espacio de los registro eliminados en el nuevo segmento.
En este caso podemos forzar que el merge se realice solo de los segmentos que contienen datos eliminados y no de la totalidad. De este modo, el segmento temporal, será de menor tamaño y podremos realizar la operación y liberar así el espacio en disco.

Para forzar el merge solo de los segmentos que contienen datos eliminados, lanzamos la invocación la API..
curl -XPOST 'localhost:9200/_forcemerge?only_expunge_deletes=true'
Referencia:

martes, 26 de septiembre de 2017

Notas sobre journal / journalctl

Algunas notas que me resultan útiles casi a diario, sobre el uso de journalctl…

Por defecto es volátil y por lo tanto no persiste tras un reboot.
Tenemos en
/run/log/journal/$ID/system.journal
Los logs de cada arranque disponible, donde $ID es un id que asigna systemd al log.
/run/log/journal/d0c4a268300a404b9cbc7a39f31a47bd/system.journal

  • Consultar logs disponibles.
journalctl --list-boots 
 0 bf51a6d4b1a749dfb22eb955a2764e84 lun 2017-09-25 20:49:23 CEST
Podremos ver salidas del tipo:
-3 XXXXX3 fecha ….
-2 XXXXX2 fecha ….
-1 XXXXX1 fecha ….
0 XXXXX0 fecha ….

  • Consultar logs de un boot determinado.
journalctl -b -3
journalctl _BOOT_ID=-3
  • Consultar logs del kernel.
journalctl -k
  • Consultar últimas entradas. 
journalctl -b -k -n 10 #(Ultimas 10 entradas de logs de kernel y boot)
  • Logs de un proceso.
journalctl /bin/xxxx #(Full path)
journalctl _PID=XXXX
  • Logs de un usuario.
journalctl _UID=XXXX
  • Logs de un servicio.
journalctl -u httpd.service
journalctl _SYSTEMD_UNIT=httpd.service
  • Logs de varios servicios.
journalctl _SYSTEMD_UNIT=XX.service + _SYSTEMD_UNIT=YY.service
  • Establecer rangos de fecha.
--since=09:30
--until=16:25
--since='30 min ago'
--until='2 days ago'
  • Logs por criticidades.
journalctl -p 2
journalctl -p err

0 emergency / 1 alert / 2 crit / 3 err / 4 warn / 5 notice / 6 info / 7 debug
  • Logs por disco.
journalctl /dev/sda
journalctl /dev/sda1
  • Check espacio usado de journal.
journalctl --disk-usage
Archived and active journals take up 8.0M on disk.
  • Permitir journal a usuarios.
El grupo ‘adm‘ tiene acceso a journal.
usermod -a -G adm USUARIO
  • Configurar persistencia de logs.
mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
chown root:systemd-journal /var/log/journal
chmod 2775 /var/log/journal
systemctl restart systemd-journal
  • Configuración general.
En el fichero:
/etc/systemd/journald.conf
Storage=
volatile –> Es volatil en /run/systemd/journal/
Persistent –> Es persistente en /var/log/journal/
Auto  –> Por defecto persistente, pero si no esta el path NO lo crea y pasa a volatil.
Nohe –> Logs a consola
Compress=  –> Por defecto true
Seal= –> Se crean claves para asegurar la integridad de los logs.
SystemMaxUse= 50M #(Por defecto 10% de filesystem, tamaño al que rota)
  • Rotado manual.
journalctl --vacuum-size=2G #(Limpiar y retener 2G)
journalctl --vacuum-time=2years #(Limpiar y retener 2 años)

lunes, 25 de septiembre de 2017

Consideraciones sobre tuning para Graylog y ElasticSearch

Algunas consideraciones sobre rendimiento para Graylog y ElasticSearch, que he ido afinando ha base de leer, probar y volver a ajustar….
NOTA:
Todas las consideraciones están basadas en pruebas de carga, con estos criterios:
1.- Inserciones de un fichero de unas 3.000.000 lineas distintas de logs.
2.- Múltiples repeticiones para intentar eliminar desviaciones en las muestras.
2.- Usando como agente graylog_sidecar.

Consideraciones sobre HW…

Graylog.

CPU (8vCPU)

Testado con 4, 6, 8, 12 y 16 vCPU’s, reajustando valores de configuración que dependen de los cores, explicados más adelante.
Hasta los 8 cores el crecimiento es lineal y la sensación de uso mejora considerablemente. Llegados a este punto ya no se percibe mejora.

RAM (8Gb)

Testado con 4, 6, 8 y 16 Gb de RAM, siempre destinando el 50% a la JVM.
El funcionamiento ha ido mejorando, sobre todo en la sensación de uso, hasta llegar a 8Gb con 4Gb para  graylog. Al subir a 16Gb, la mejora deja de ser significativa, usando dashboards y lanzando queries mientras se insertan datos.

HD (N.A)

No he podido detectar repercusión mencionable. He realizado pruebas pasando el journal que que usa como buffer, a memoria e incluso deshabilitándolo.
message_journal_enabled = true --> false
message_journal_dir = /var/lib/graylog-server/journal

Conclusión:

Con estas pruebas «8vCPU / 8Gb Ram» parece razonable, llegados a este punto y con las pruebas realizadas, si se necesita más rendimiento, lo más recomendable parece un crecimiento horizontal, usando algún tipo de balanceo.

ElasticSearch.

CPU (8vCPU)

Testado con 4, 6, 8, 12… Pasar de 4 a 8 vCPU ha supuesto un incremento de más del 20%. en inserciones. Seguir subiendo no parece lo mejor ya que desde los 8vCPU, se deja de notar mejoría y el uso del CPU del equipo, esta lejos de ser alto.

RAM

16Gb ha sido el único valor testado. En la documentación que he podido consultar por parte del fabricante, generalizan nodos con cerca de 64Gb Ram. Así que invertir aquí puede ser buena idea.

HD

Toda la documentación del fabricante indica que se recomiendan discos lo más rápidos posibles, y creo que es evidente el motivo, pero la verdad, es que he podido probar discos SATA, SAS 7200, SAS 10000 y SSD y no he sido capaz de cargar los discos, como para notar diferencias y detectar algún cuello de botella. Supongo que en entornos productivos con inserciones más grandes y queries exigentes, si debe existir impacto.

Conclusión:

Con las pruebas realizadas la máquina más optima, «Recursos/Rendimiento», parece «8vCPU / 16Gb Ram».
Según la documentación del fabricante, no parece que el crecimiento vertical (más recursos) sea el camino a seguir. Todo indica, que es preferible múltiples máquinas de pocos recursos que menos máquinas de más recursos.
También es cierto que en entornos productivos, como he dicho antes, elasticsearch hace recomendaciones con muchísimo más HW y los considera máquinas pequeñas …  (16vCPU/64Gb RAM) por ejemplo.

Consideraciones sobre Software…

Graylog.

He probado diferentes parámetros e intentado ajustarlos en función del HW disponible. Los que han tenido repercusión sobre el rendimiento han sido los siguientes…

output_batch_size = 500 --> 5000
output_flush_interval = 1
Estos parámetros indican que los datos son enviados a ElasticSearch cada 5000 mensajes o cada segundo, lo que antes suceda. Para inserciones altas, 500 es un número demasiado bajo, lo que hace que intentemos insertar demasiadas veces, bajando así el rendimiento.

processbuffer_processors = 5 --> 8 --> 10 --> 20 --> 8
outputbuffer_processors = 3 --> 8 --> 10 --> 20 --> 8
inputbuffer_processors = 2 --> 6 --> 8 --> 10 --> 20 --> 8
He podido probar con la lista de valores indicada, sin detectar cambios una vez superado el umbral del número de cores disponibles en la máquina que corre graylog. Así que … No se recomienda pasar del número de cores disponibles.

ElasticSearch.

index.refresh_interval: 30s
curl -XPUT 'X.X.X.X:9200/graylog2_001/_settings' -d '{
    "index" : {
        "refresh_interval" : "30s"
    }
}'
Con este curl, podemos realizar el cambio de valor en caliente.
Este es el valor que más repercusión ha tenido en el rendimiento con mucha diferencia. En las guías de Graylog, se indica que es necesario y que tiene mucha repercusión en el rendimiento, y así es… Cambio obligado si se usa graylog
Notas:
Aquí simplemente unas observaciones que tienen repercusión sobre el rendimiento pero que dependen tanto de cada caso particular que no es posible dar números…
  • Más nodos de elasticsearch (con al menos un número de shards igual al número de nodos ), mejoran el rendimiento en queries.
  • Menos nodos (Por lo tanto menos menos shards, pero más grandes, mejoran la inserción).