En el mundo informático, la automatización de tareas repetitivas puede ahorrar tiempo y reducir errores. Una de estas tareas consiste en comprobar la presencia de archivos o carpetas específicos en varios directorios. Ya sea para el cumplimiento de normativas, la supervisión del sistema o la solución de problemas, disponer de una forma automática de comprobar la presencia de archivos puede ser muy valioso para los profesionales de TI y los proveedores de servicios gestionados (MSP). Este post explora un script Bash diseñado para agilizar este proceso, garantizando la eficiencia y la fiabilidad en la gestión de archivos.
Background
Este script para comprobar la presencia de archivos es especialmente útil para los profesionales de TI que necesitan verificar la existencia de archivos o carpetas críticos de forma regular. Proporciona una solución automatizada para buscar en directorios, asegurándose de comprobar la presencia de archivos importantes o identificando cuándo faltan. Esta capacidad es crucial en varios escenarios, como validar las ubicaciones de las copias de seguridad, garantizar la presencia de archivos de configuración o confirmar el despliegue de aplicaciones críticas.
El script para comprobar la presencia de archivos
#!/usr/bin/env bash # Description: Alert if a specified file or folder is found in a directory or subdirectory you specify. # # 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://www.ninjaone.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). # # Below are all the (case sensitive) valid parameters for this script. # Only the path to search and name of file or folder are required! # # Parameter: --path "/opt/NinjaRMM/programdata" # Required # Base path to search for files or folders. # # Parameter: --name "ninjarmm-cli" # Required # Name of the file or folder to search for. # Notes: # If the name is not provided, the script will search for the path only. # This is case sensitive and accepts wildcards. # # Parameter: --type "Files Or Folders" # Required # Search for files or folders. # # Parameter: --type "Files Only" # Required # Searches for files only. # # Parameter: --type "Folders Only" # Required # Searches for folder only. # # Parameter: --timeout 10 # Optional and defaults to 30 minutes # Time in minutes to wait for the search to complete before timing out. # # Parameter: --customfield "myCustomField" # Optional # Custom Field to save the search results to. die() { local _ret="${2:-1}" test "${_PRINT_HELP:-no}" = yes && print_help >&2 echo "$1" >&2 exit "${_ret}" } begins_with_short_option() { local first_option all_short_options='h' first_option="${1:0:1}" test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 } # Initize arguments _arg_path= _arg_name= _arg_type= _arg_timeout=30 _arg_customfield= print_help() { printf '%s\n' "Check existence of a file or folder" printf 'Usage: %s [--path <arg>] [--name <arg>] [--type <"Files Only"|"Folders Only"|"Files Or Folders">] [--timeout <30>] [--customfield <arg>] [-h|--help]\n' "$0" printf '\t%s\n' "-h, --help: Prints help" } parse_commandline() { while test $# -gt 0; do _key="$1" case "$_key" in --path) test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 _arg_path="$2" shift ;; --path=*) _arg_path="${_key##--path=}" ;; --name) test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 _arg_name="$2" shift ;; --name=*) _arg_name="${_key##--name=}" ;; --type) test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 _arg_type="$2" shift ;; --type=*) _arg_type="${_key##--type=}" ;; --timeout) test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 _arg_timeout="$2" shift ;; --timeout=*) _arg_timeout="${_key##--timeout=}" ;; --customfield) test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 _arg_customfield="$2" shift ;; --customfield=*) _arg_customfield="${_key##--customfield=}" ;; -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 "$@" function SetCustomField() { customfieldName=$1 customfieldValue=$2 if [ -f "${NINJA_DATA_PATH}/ninjarmm-cli" ]; then if [ -x "${NINJA_DATA_PATH}/ninjarmm-cli" ]; then if "$NINJA_DATA_PATH"/ninjarmm-cli get "$customfieldName" >/dev/null; then # check if the value is greater than 10000 characters if [ ${#customfieldValue} -gt 10000 ]; then echo "[Warn] Custom field value is greater than 10000 characters" fi if ! echo "${customfieldValue::10000}" | "$NINJA_DATA_PATH"/ninjarmm-cli set --stdin "$customfieldName"; then echo "[Warn] Failed to set custom field" else echo "[Info] Custom field value set successfully" fi else echo "[Warn] Custom Field ($customfieldName) does not exist or agent does not have permission to access it" fi else echo "[Warn] ninjarmm-cli is not executable" fi else echo "[Warn] ninjarmm-cli does not exist" fi } if [ ! "$(command -v timeout)" ]; then notimeout=true # If the timeout command does not exist, create a function to mimic the timeout command function timeout() { perl -e 'alarm shift; exec @ARGV' "$@"; } fi parentSearchPath=$_arg_path leafSearchName=$_arg_name searchType=$_arg_type timeout=$_arg_timeout customField=$_arg_customfield # Get values from Script Variables if [[ -n "${pathToSearch}" ]]; then parentSearchPath="${pathToSearch}" fi if [[ -n "${nameOfFileOrFolder}" ]]; then leafSearchName="${nameOfFileOrFolder}" fi if [[ -n "${filesOrFolders}" && "${filesOrFolders}" != "null" ]]; then searchType="${filesOrFolders}" fi if [[ -n "${searchTimeout}" && "${searchTimeout}" != "null" ]]; then timeout="${searchTimeout}" fi if [[ -n "${customFieldName}" && "${customFieldName}" != "null" ]]; then customField="${customFieldName}" fi # Check if parentSearchPath is a link and replace it with the resolved path if [ -L "${parentSearchPath}" ]; then echo "[Info] Path to Search is a link: ${parentSearchPath} -> $(readlink -f "${parentSearchPath}")" echo "[Info] Will use the resolved path to search" parentSearchPath=$(readlink -f "${parentSearchPath}") fi if [[ -z "${parentSearchPath}" ]]; then echo "[Error] Path to Search is empty" exit 1 fi # Check if path exists if [ -e "${parentSearchPath}" ]; then echo "[Info] Path ${parentSearchPath} exists" else echo "[Error] Path to Search ${parentSearchPath} does not exist or is an invalid path" exit 1 fi # Check if timeout is a number if ! [[ "${timeout}" =~ ^[0-9]+$ ]]; then echo "[Error] Timeout is not a number" exit 1 fi # Check if timeout is not in the range of 1 to 120 if [[ "${timeout}" -lt 1 || "${timeout}" -gt 120 ]]; then echo "[Error] Timeout is not in the range of 1 to 120" exit 1 fi # Check if search type is valid if $notimeout; then # If the timeout command does not exist, convert the timeout to minutes timeout=$((timeout * 60)) else # If the timeout command does exist, add m to the end of the string timeout="${timeout}m" fi if [[ $OSTYPE == 'darwin'* ]]; then if ! plutil -lint /Library/Preferences/com.apple.TimeMachine.plist >/dev/null; then echo "This script requires ninjarmm-macagent to have Full Disk Access." echo "Add ninjarmm-macagent to the Full Disk Access list in System Preferences > Security & Privacy, quit the app, and re-run this script." exit 1 fi fi # Search for files or folders if [[ -n "${leafSearchName}" && "${leafSearchName}" != "null" ]]; then if [[ "${searchType}" == *"Files"* && "${searchType}" == *"Only"* ]]; then echo "[Info] Searching for files only" # Search for files only # Use timeout to prevent the find command from running indefinitely foundPath=$(timeout "${timeout}" find "$parentSearchPath" -type f -name "$leafSearchName" 2>/dev/null) exitcode=$? if [[ $exitcode -eq 0 || $exitcode -eq 124 ]]; then if [[ -n $foundPath ]]; then echo "[Alert] File Found" fi fi elif [[ "${searchType}" == *"Folders"* && "${searchType}" == *"Only"* ]]; then echo "[Info] Searching for folders only" # Search for folders only # Use timeout to prevent the find command from running indefinitely foundPath=$(timeout "${timeout}" find "$parentSearchPath" -type d -name "$leafSearchName" 2>/dev/null) exitcode=$? if [[ $exitcode -eq 0 || $exitcode -eq 124 ]]; then if [[ -n $foundPath ]]; then echo "[Alert] File Found" fi fi elif [[ "${searchType}" == *"Files"* && "${searchType}" == *"Folders"* ]]; then echo "[Info] Searching for files or folders" # Search for files or folders # Use timeout to prevent the find command from running indefinitely foundPath=$(timeout "${timeout}" find "$parentSearchPath" -name "$leafSearchName" 2>/dev/null) exitcode=$? if [[ $exitcode -eq 0 || $exitcode -eq 124 ]]; then if [[ -n $foundPath ]]; then echo "[Alert] File Found" fi fi else echo "[Error] Invalid search type" echo "Valid search types: Files Only, Folders Only, Files Or Folders" exit 1 fi elif [[ -z "${leafSearchName}" ]]; then echo "[Info] Searching in path only" # Search in path only # Use timeout to prevent the find command from running indefinitely foundPath=$(timeout "${timeout}" find "$parentSearchPath") exitcode=$? if [[ $exitcode -eq 0 || $exitcode -eq 124 ]]; then if [[ -n $foundPath ]]; then echo "[Alert] File Found" fi fi fi # Check exit code if [[ -n $foundPath ]]; then # Split the string into an array IFS=$'\n' read -rd '' -a foundPathArray <<<"${foundPath}" # Print each element of the array for element in "${foundPathArray[@]}"; do echo "[Alert] ${element} exists" done elif [[ -z $foundPath ]]; then echo "[Warn] Could not find a file or folder" exit 1 else # If the find command fails to find the file or folder # Figure out the grammer for the search type if [[ "${searchType}" == *"Only"* ]]; then if [[ "${searchType}" == *"Files"* ]]; then searchTypeInfo="file" elif [[ "${searchType}" == *"Folders"* ]]; then searchTypeInfo="folder" fi elif [[ "${searchType}" == *"Files"* && "${searchType}" == *"Folders"* ]]; then searchTypeInfo="file or folder" fi echo "[Info] Could not find a ${searchTypeInfo} in the path ${parentSearchPath} with the name containing: ${leafSearchName}" fi # If foundPath contains "Alarm clock:" then the command timed out if [[ "${foundPath}" == *"Alarm clock:"* ]]; then echo "[Alert] Timed out searching for file or folder" # Remove "Alarm clock: *" from the string foundPath=${foundPath/Alarm clock: [0-9]*//} fi # If command times out if [[ $exitcode -ge 124 && $exitcode -le 127 || $exitcode -eq 137 ]]; then echo "[Alert] Timed out searching for file or folder" echo "timeout exit code: $exitcode" echo " 124 if COMMAND times out, and --preserve-status is not specified" echo " 125 if the timeout command itself fails" echo " 126 if COMMAND is found but cannot be invoked" echo " 127 if COMMAND cannot be found" echo " 137 if COMMAND (or timeout itself) is sent the KILL (9) signal (128+9)" echo "find command result: $foundPath" exit 1 fi # Save to custom field if [[ -n "${customField}" && "${customField}" != "null" ]]; then SetCustomField "${customField}" "${foundPath}" fi
Análisis detallado
El script para comprobar la presencia de archivos funciona tomando varios parámetros para personalizar el proceso de búsqueda. Aquí tienes un desglose detallado de su funcionalidad:
1. Parámetros e inicialización:
- –path: Especifica el directorio base en el que buscar.
- –name: Define el nombre del archivo o carpeta a buscar, admitiendo comodines.
- –type: Determina si se buscan archivos, carpetas o ambos.
- –timeout: Establece el tiempo máximo para la operación de búsqueda, por defecto 30 minutos.
- –customfield: Permite guardar el resultado de la búsqueda en un campo personalizado.
2. Análisis de argumentos: El script para comprobar la presencia de archivos analiza los argumentos de la línea de comandos para inicializar los parámetros de búsqueda. Si falta algún parámetro requerido, proporciona un mensaje de error y sale.
3. Ejecución de la búsqueda:
- El script para comprobar la presencia de archivos resuelve cualquier enlace simbólico en la ruta de búsqueda.
- Verifica que la ruta especificada existe y es válida.
- Garantiza que el tiempo de espera está dentro del rango aceptable (de 1 a 120 minutos).
4. Búsqueda de archivos o carpetas: Dependiendo del tipo especificado (archivos, carpetas o ambos), el script para comprobar la presencia de archivos utiliza el comando find con un tiempo de espera para localizar los elementos deseados. Si se encuentra, avisa al usuario y, opcionalmente, guarda el resultado en un campo personalizado.
5. Tratamiento de errores e informes: El script para comprobar la presencia de archivos incluye un completo tratamiento de errores, garantizando que problemas como rutas no válidas, valores de tiempo de espera incorrectos o archivos/carpetas inexistentes se comuniquen claramente al usuario.
Posibles casos de uso
Estudio de caso: Verificación de la conformidad informática
Un profesional de TI es responsable de garantizar que los archivos de configuración de seguridad críticos estén presentes en todos los servidores. Con este script para comprobar la presencia de archivos y carpetas, puede automatizar el proceso de verificación:
1. Configuración:
- –path: /etc/security
- –name: security.conf
- –type: Sólo archivos
- –timeout: 10
2. Ejecución: El script para comprobar la presencia de archivos y carpetas busca el archivo security.conf en la ruta especificada dentro del periodo de tiempo establecido. Si se encuentra, registra una alerta; si no, notifica al profesional de TI, lo que permite una rápida remediación.
Comparaciones
En comparación con la verificación manual o el uso de comandos básicos del shell, este script para comprobar la presencia de carpetas ofrece varias ventajas:
- Automatización: Reduce la necesidad de controles manuales.
- Gestión del tiempo de espera: Evita búsquedas prolongadas imponiendo un tiempo de espera.
- Informes personalizados: Permite guardar los resultados en campos personalizados para su posterior procesamiento o para la elaboración de informes de cumplimiento.
Otros métodos, como el uso de ls o comandos de prueba en Bash, carecen de estas características avanzadas, por lo que este script para comprobar la presencia de archivos es una solución más robusta y eficiente.
FAQ
- ¿Qué ocurre si se agota el tiempo de espera del script para comprobar la presencia de archivos?
El script informa de un tiempo de espera y sale con un código de error apropiado, asegurándose de que el usuario es consciente de que la búsqueda estaba incompleta. - ¿Puedo buscar varios tipos de archivos simultáneamente?
No, actualmente el script para comprobar la presencia de archivos permite buscar archivos o carpetas basándose en un único patrón de nombre cada vez. - ¿Cómo se gestionan los enlaces simbólicos en la ruta de búsqueda?
El script para comprobar la presencia de archivos resuelve automáticamente los enlaces simbólicos, asegurando que la búsqueda se realiza en el directorio correcto.
Implicaciones
El uso de este script para comprobar la presencia de archivos puede mejorar significativamente la seguridad informática al garantizar la presencia de archivos y carpetas críticos. La verificación automatizada ayuda a mantener el cumplimiento de las políticas de seguridad y reduce el riesgo de omitir archivos importantes, lo que podría provocar vulnerabilidades o fallos en el sistema.
Recomendaciones
- Realiza auditorías de forma periódica: Programa la ejecución periódica del script para mantener actualizada la verificación de los archivos críticos.
- Utiliza campos personalizados: Aprovecha la opción de campos personalizados para realizar un seguimiento e informar sistemáticamente de los resultados de búsqueda.
- Ajusta el tiempo de espera: Ajusta el parámetro de tiempo de espera en función del tamaño previsto del directorio y del rendimiento del sistema para evitar retrasos innecesarios.
Reflexiones finales
Este script Bash es una potente herramienta para los profesionales de TI, ya que proporciona un método automatizado y fiable para comprobar la presencia de archivos y carpetas. Al integrar este script para comprobar la presencia de archivos en las comprobaciones rutinarias, los MSP pueden garantizar una mayor eficacia y seguridad en sus operaciones. Herramientas como NinjaOne pueden mejorar aún más este proceso al ofrecer soluciones integrales de gestión de TI, lo que facilita la implementación, supervisión y gestión de scripts en múltiples sistemas.
La automatización de la gestión de archivos no sólo ahorra tiempo, sino que también aumenta la precisión, garantizando que los archivos críticos estén siempre donde tienen que estar.