Cómo monitorizar los archivos de registro y detectar patrones de texto específicos en Linux usando un script bash

Monitorizar los archivos de registro y detectar patrones de texto específicos es una tarea crucial para los profesionales de TI, especialmente en el contexto de la administración de sistemas y la ciberseguridad. Los scripts automatizados que pueden alertar sobre cadenas de texto específicas dentro de los archivos son herramientas muy valiosas en la caja de herramientas de cualquier profesional de TI.

El script proporcionado cumple esta tarea eficazmente, ofreciendo una solución robusta para monitorizar los archivos de registro y alertar de la aparición de cadenas de texto específicas. Este post profundizará en la funcionalidad del script, explorará sus aplicaciones en el mundo real y discutirá las mejores prácticas para su uso.

Comprender el script y su significado

En los entornos de TI, diversos sistemas, aplicaciones y procesos generan continuamente archivos de registro. Estos registros contienen información vital sobre las operaciones del sistema, errores, eventos de seguridad y actividades de los usuarios. Sin embargo, supervisar manualmente estos archivos en busca de eventos críticos o cadenas de texto es poco práctico y propenso a errores. Aquí es donde la automatización mediante scripts resulta esencial.

El script proporcionado está diseñado para buscar un texto específico dentro de un archivo de registro y generar una alerta cuando se encuentra ese texto. Este script es especialmente útil para proveedores de servicios gestionados (MSP) y administradores de TI que necesitan monitorizar los archivos de registro para detectar incidentes de seguridad, errores de aplicaciones o cualquier otro evento significativo que pueda requerir atención inmediata.

El script para monitorizar los archivos de registro

#!/usr/bin/env bash

# Description: Alert when the specified Text is found in a text file.
#
# Release Notes: Initial Release
#   By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://ninjastage2.wpengine.com/terms-of-use.
#   Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
#   Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
#   Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
#   Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
#   Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
#   Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
#   EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#
# Text to trigger on: [Alert]
#
# Below are all the valid parameters for this script.
# Preset Parameter: --file "/opt/MyLogFile.log" --text batman
#   Alerts when the text "batman" is found in the file /opt/MyLogFile.log
#    This is Case Sensitive
#     Example where it will alert: "I am batman!"
#     Example where it will alert: "Iambatman!"
#     Example where it will not alert: "IamBatman!"
#     Example where it will not alert: "I am Batman!"
#
# Preset Parameter: --file "/opt/MyLogFile.log" --text Batman --caseInsensitive true
#   Alerts when the text "Batman" is found in the file /opt/MyLogFile.log, but is case insensitive
#    This is Case Insensitive
#     Example where it will alert: "I am batman!"
#     Example where it will alert: "Iambatman!"
#
# Preset Parameter: --file "/opt/MyLogFile.log" --text Batman --wholeWord true
#   Alerts when the text "Batman" is found in the file /opt/MyLogFile.log, but only if it is a word in a sentence.
#    This is Case Sensitive
#     Example where it will alert: "I am Batman!"
#     Example where it will not alert: "IamBatman!"
#

# Determines whether or not help text is necessary and routes the output to stderr
die() {
    local _ret="${2:-1}"
    test "${_PRINT_HELP:-no}" = yes && print_help >&2
    echo "$1" >&2
    exit "${_ret}"
}

# Function that evaluates whether a value passed to it begins by a character
# that is a short option of an argument the script knows about.
# This is required in order to support getopts-like short options grouping.
begins_with_short_option() {
    local first_option all_short_options='ftiwh'
    first_option="${1:0:1}"
    test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
}

# THE DEFAULTS INITIALIZATION - OPTIONALS
_arg_file=
_arg_text=
_arg_caseInsensitive="false"
_arg_wholeWord="false"

# Help text function for when invalid input is encountered
print_help() {
    printf '%s\n' "Alert when the specified Text is found in a text file."
    printf 'Usage: %s [-f|--file [path to file]] [-t|--text [text to search]] [-i|--caseInsensitive <true|false>] [-w|--wholeWord <true|false>] [-h|--help]\n' "$0"
    printf '\t%s\n' "-f, --file: path to a log file"
    printf '\t%s\n' "-t, --text: text to alert when found"
    printf '\t%s\n' "-i, --caseInsensitive: search text with case insensitivity (default: false)"
    printf '\t%s\n' "-w, --wholeWord: search for text as a whole word (default: false)"
    printf '\t%s\n' "-h, --help: Prints help"
}

# Grabbing the parameters and parsing through them.
parse_commandLine() {
    while test $# -gt 0; do
        _key="$1"
        case "$_key" in
        -f | --file)
            test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
            _arg_file="$2"
            shift
            ;;
        --file=*)
            _arg_file="${_key##--file=}"
            ;;
        -f*)
            _arg_file="${_key##-f}"
            ;;
        -t | --text)
            test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
            _arg_text="$2"
            shift
            ;;
        --text=*)
            _arg_text="${_key##--text=}"
            ;;
        -t*)
            _arg_text="${_key##-t}"
            ;;
        -i | --caseInsensitive)
            test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
            _arg_caseInsensitive="$2"
            shift
            ;;
        --caseInsensitive=*)
            _arg_caseInsensitive="${_key##--caseInsensitive=}"
            ;;
        -i*)
            _arg_caseInsensitive="${_key##-i}"
            ;;
        -w | --wholeWord)
            test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
            _arg_wholeWord="$2"
            shift
            ;;
        --wholeWord=*)
            _arg_wholeWord="${_key##--wholeWord=}"
            ;;
        -w*)
            _arg_wholeWord="${_key##-w}"
            ;;
        -h | --help)
            print_help
            exit 0
            ;;
        -h*)
            print_help
            exit 0
            ;;
        *)
            _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
            ;;
        esac
        shift
    done
}

parse_commandLine "$@"

text=$_arg_text
file=$_arg_file
caseInsensitive=$_arg_caseInsensitive
wholeWord=$_arg_wholeWord

# Check if Script Variables where used and overwrite command line parameters
if [[ -n "${textToMatch}" ]]; then
    text=$textToMatch
fi
if [[ -n "${textFile}" ]]; then
    file=$textFile
fi
if [[ -n "${matchWholeWord}" ]]; then
    wholeWord=$matchWholeWord
fi
if [[ -n "${insensitiveToCase}" ]]; then
    caseInsensitive=$insensitiveToCase
fi

# Check if text is not an empty string
if [[ -z "${text}" ]]; then
    echo "[Error] Text not specified"
    exit 2
fi

# Check if text is not an empty string
if [[ -z "${file}" ]]; then
    echo "[Error] File not specified"
    exit 2
fi

# Does file exit and is readable
if [ -f "${file}" ]; then
    echo "[Info] File \"${file}\" exists"
    if [ -r "${file}" ]; then
        echo "[Info] File \"${file}\" is readable"
    else
        echo "[Error] File \"${file}\" is not readable"
        exit 2
    fi
else
    echo "[Error] File \"${file}\" does not exists"
    exit 2
fi

# Detect
count=0
if [[ "${wholeWord}" == "true" ]]; then
    if [[ "${caseInsensitive}" == "true" ]]; then
        count=$(grep -c -i -n -w "$text" "$file")
    else
        count=$(grep -c -n -w "$text" "$file")
    fi
else
    if [[ "${caseInsensitive}" == "true" ]]; then
        count=$(grep -c -i -n -e "$text" "$file")
    else
        count=$(grep -c -n -e "$text" "$file")
    fi
fi

# Alert
if ((count > 0)); then
    echo "[Alert] Found text in file"
    exit 1
else
    echo "[Info] Not found text in file"
    exit 0
fi

 

Desglose detallado del script

Veamos con más detalle cómo funciona este script:

1. Parsing de los parámetros

  • El script comienza definiendo parámetros por defecto como _arg_file, _arg_text, _arg_caseInsensitive y _arg_wholeWord. A continuación, estos parámetros se analizan desde la línea de comandos, lo que permite al usuario especificar el archivo que se va a supervisar, el texto que se va a buscar y si la búsqueda debe distinguir entre mayúsculas y minúsculas o limitarse a palabras enteras.

2.  Argumentos de la línea de comandos: 

  • Los usuarios pueden utilizar varios argumentos como –file, –text, –caseInsensitive y –wholeWord para personalizar el comportamiento del script. Por ejemplo, –file especifica la ruta al archivo de registro, mientras que –text indica el texto que se debe buscar. El script también admite búsquedas sin distinción entre mayúsculas y minúsculas y búsquedas restringidas a palabras completas.

3.  Validación:

  • El script realiza varias comprobaciones de validación, como asegurarse de que se proporciona tanto el texto a buscar como la ruta del archivo. También comprueba si el archivo especificado existe y es legible. Estas validaciones impiden que el script se ejecute en condiciones inadecuadas, evitando así posibles errores.

4. Búsqueda del texto:

  • La funcionalidad principal del script gira en torno al comando grep, que busca el texto especificado dentro del archivo de registro. Dependiendo de los parámetros proporcionados, el script puede realizar búsquedas sin distinguir entre mayúsculas y minúsculas o buscar sólo palabras completas. El resultado del comando grep se almacena en la variable count, que indica cuántas veces se ha encontrado el texto especificado.

5.  Mecanismo de alerta:

  • Si el texto se encuentra dentro del archivo, el script genera una alerta imprimiendo un mensaje y saliendo con un código de estado 1. Si no se encuentra el texto, sale con un código de estado 0, indicando que no hay condición de alerta.

Casos de uso concretos

Piensa en un MSP encargado de supervisar los registros del servidor de un cliente para detectar amenazas de seguridad específicas, como intentos fallidos de inicio de sesión. Este script podría configurarse para buscar en los archivos de registro frases como “Contraseña fallida” o “Fallo de autenticación”. Cuando el script detecte estas frases, alertará inmediatamente al MSP, permitiéndole tomar medidas rápidas para investigar y mitigar posibles brechas de seguridad.

Otro ejemplo podría ser un administrador de sistemas que necesita supervisar los registros de aplicaciones en busca de errores críticos. Configurando el script para que busque palabras clave como “ERROR” o “CRÍTICO”, el administrador puede asegurarse de que se le avisa rápidamente de cualquier problema que pueda afectar al rendimiento o la disponibilidad de la aplicación.

Comparación con otros métodos

Aunque hay varias herramientas y métodos disponibles para la monitorización de archivos de registro, como el uso de soluciones de gestión de registros centralizadas como ELK Stack (Elasticsearch, Logstash, Kibana) o herramientas de monitorización basadas en la nube, este script ofrece una solución ligera y directa que no requiere infraestructura adicional. Es ideal para situaciones en las que la sencillez y la rapidez de implantación son fundamentales, o en las que un sistema de supervisión completo puede resultar excesivo.

Preguntas frecuentes

  • P: ¿Se puede utilizar este script en sistemas que no sean Linux?
  • R: Este script está diseñado para sistemas tipo Unix, como Linux. Se basa en comandos como grep, que son estándar en estos entornos. Aunque en teoría podría adaptarse a otros sistemas, requeriría modificaciones.
  • P: ¿Cómo gestiona el script los archivos de registro de gran tamaño?
  • R: El script utiliza grep, que es eficaz incluso con archivos de gran tamaño. Sin embargo, en el caso de archivos extremadamente grandes, el rendimiento podría verse afectado. En estos casos, puede ser aconsejable utilizar un mecanismo de rotación de registros o herramientas de gestión de registros más avanzadas.
  • P: ¿Qué ocurre si se encuentran varias instancias del texto?
  • R: El script cuenta todas las instancias del texto en el archivo y activa una alerta si se encuentra alguna coincidencia, independientemente del número de ocurrencias.

Implicaciones para la seguridad informática

La capacidad de supervisar los archivos de registro en busca de cadenas de texto específicas es crucial para mantener la seguridad y la estabilidad de los sistemas informáticos. Este script puede ser un componente crítico de una estrategia de seguridad más amplia, ayudando a los profesionales de TI a detectar y responder rápidamente a las amenazas potenciales. Al automatizar el proceso de supervisión, el script reduce el riesgo de que se pasen por alto alertas y garantiza que los problemas críticos se señalen en tiempo real.

Recomendaciones para utilizar el script

  • Actualiza regularmente el script: asegúrate de que el script se mantiene actualizado con las últimas funciones y mejoras. Las actualizaciones periódicas también pueden ayudar a abordar posibles vulnerabilidades de seguridad.
  • Intégralo con otras herramientas: considera la posibilidad de integrar este script con herramientas de notificación, como alertas por correo electrónico o SMS, para garantizar que las alertas se reciban con prontitud, incluso cuando el administrador no esté supervisando activamente el sistema.
  • Prueba en un entorno seguro: antes de desplegar el script en un entorno de producción, pruébalo en un entorno controlado para asegurarte de que se comporta como se espera con tus archivos de registro y casos de uso específicos.

Reflexiones finales

Monitorizar los archivos de registro en busca de cadenas de texto específicas es una práctica fundamental en la administración y seguridad de TI. Este script proporciona una solución sencilla pero potente para automatizar este proceso, facilitando a los profesionales de TI la detección y respuesta a eventos críticos en tiempo real. Para aquellos que utilizan NinjaOne, este tipo de script podría ser una parte integral de su estrategia global de monitoreo de TI, asegurando que sus sistemas permanezcan seguros y operativos en todo momento.

Categorías:

Quizá también te interese…

×

¡Vean a NinjaOne en acción!

Al enviar este formulario, acepto la política de privacidad de NinjaOne.

Términos y condiciones de NinjaOne

Al hacer clic en el botón “Acepto” que aparece a continuación, estás aceptando los siguientes términos legales, así como nuestras Condiciones de uso:

  • Derechos de propiedad: NinjaOne posee y seguirá poseyendo todos los derechos, títulos e intereses sobre el script (incluidos los derechos de autor). NinjaOne concede al usuario una licencia limitada para utilizar el script de acuerdo con estos términos legales.
  • Limitación de uso: solo podrás utilizar el script para tus legítimos fines personales o comerciales internos, y no podrás compartirlo con terceros.
  • Prohibición de republicación: bajo ninguna circunstancia está permitido volver a publicar el script en ninguna biblioteca de scripts que pertenezca o esté bajo el control de cualquier otro proveedor de software.
  • Exclusión de garantía: el script se proporciona “tal cual” y “según disponibilidad”, sin garantía de ningún tipo. NinjaOne no promete ni garantiza que el script esté libre de defectos o que satisfaga las necesidades o expectativas específicas del usuario.
  • Asunción de riesgos: el uso que el usuario haga del script corre por su cuenta y riesgo. El usuario reconoce que existen ciertos riesgos inherentes al uso del script, y entiende y asume cada uno de esos riesgos.
  • Renuncia y exención: el usuario no hará responsable a NinjaOne de cualquier consecuencia adversa o no deseada que resulte del uso del script y renuncia a cualquier derecho o recurso legal o equitativo que pueda tener contra NinjaOne en relación con su uso del script.
  • CLUF: si el usuario es cliente de NinjaOne, su uso del script está sujeto al Contrato de Licencia para el Usuario Final (CLUF).