¿Por qué debería usar scripts bash para realizar sincronizaciones de carpetas y copias de seguridad??
Bash es, con mucho, el intérprete de lenguaje de comando más popular y utilizado compatible con SH. Hoy puede encontrar bash en casi todas partes, incluido Microsoft Windows con el nuevo subsistema de Windows para Linux. Prácticamente toda la distribución de GNU/Linux viene con BASH como el shell predeterminado. Lo mismo se aplica a macOS y algunos otros sistemas operativos similares a unix.
Bash no es solo un lenguaje de comando; Como otras conchas Unix, Bash es tanto un lenguaje de programación como un intérprete de comando. Técnicamente hablando, el lado de la programación de un shell brinda al usuario habilidades y características para combinar utilidades del sistema o shell en un archivo. El usuario puede crear comandos simplemente combinando comandos en un archivo de texto; Estos tipos especiales de archivos de texto que incluyen una colección de comandos se denominan scripts de shell y, cuando esos archivos reciben permiso para ejecutar, el intérprete de shell los ve como un solo comando.
La ventaja de un script bash es que puede usar herramientas de línea de comandos directamente dentro de él sin la necesidad de importar o bibliotecas externas de origen. Estas herramientas de línea de comandos y utilidades incorporadas son potentes y pueden interactuar directamente con el sistema operativo sin compilación o intérpretes adicionales; Por lo general, las utilidades centrales y las interfaces de línea de comandos, como asombrar, Xargs, encontrar, y grep, puede tener un rendimiento mucho mejor que usar scripts de python y sus bibliotecas, por ejemplo,. No es difícil encontrar personas que realicen análisis de datos avanzados utilizando solo script bash y utilidades integradas en GNU. Otros afirman que este tipo de enfoque puede ser de 235 x más rápido que un clúster Hadoop, lo que no es tan difícil de creer considerando algunas monstruosidades de agrupación que puede encontrar hoy en día para adaptarse a los malos diseños de software.
En este asunto, siempre surge una pregunta: si Bash es tan poderosa, ¿por qué no usarla para automatizar todas las cosas aburridas?? La sintaxis bash es simple y pragmática: le brinda la capacidad de combinar programas para automatizar tareas comunes. Sin embargo, cuando el script necesita lidiar con múltiples condiciones o acumular demasiados propósitos, es hora de considerar un lenguaje de programación más robusto, como C u otros lenguajes de script, donde Python y Perl son buenos ejemplos.
Por otro lado, los scripts bash son muy buenos para tareas individuales como la intención de este artículo: combinar utilidades con capacidades para verificar los cambios en una carpeta específica y luego sincronizar sus archivos. Un script bash puede adaptarse perfectamente a esta tarea.
¿Qué necesitas para realizar sincronización o autobackups??
Hay una gran lista de diferentes métodos para sincronizar carpetas y archivos. El número de aplicaciones que se pueden usar para lograr esta tarea simple es enorme, y algunas de ellas son soluciones de terceros. Sin embargo, Este artículo le muestra una forma más elegante de lograr lo mismo usando solo inotifywait y rsync En un guión de Bash. En general, esta solución será ligera, económica y, por qué no decir, más segura. En esencia, solo se requieren herramientas inotify, rsync y un bucle de tiempo para completar esta misión.
Cómo usar inotifywait para autobuses y sincronizaciones?
inotifywait Utiliza la API inotify para esperar cambios en los archivos. Este comando fue especialmente diseñado para usarse en scripts de shell. Una característica poderosa de inotifywait es verificar los cambios continuamente; Tan pronto como ocurren nuevos eventos, inotifywait Imprime las modificaciones y salidas.
inotifywait Proporciona dos opciones que son muy interesantes para la sincronización de la carpeta o las copias de seguridad en tiempo real. El primero es el -riñonal, -recursivo opción; Como su nombre lo indica, esta bandera observa las profundidades de subdirectorios ilimitados de un directorio específico aprobado como argumentos a inotifywait, excluyendo enlaces simbólicos.
El -mi, -evento la bandera proporciona otra característica interesante. Esta opción requiere una lista de eventos predefinidos. La documentación de inotify-tool enumera más de 15 eventos para inotifywait; Pero un sistema de copia de seguridad y sincronización simple requiere solo el eliminación, modificar y crear eventos.
El siguiente comando es un buen ejemplo de un escenario del mundo real:
$ inotifywait -r -e modificar, crear, eliminar/home/userdir/documentos
En este caso, el comando espera cambios: modificaciones, creaciones de archivo o carpeta o exclusiones de cualquier tipo - en el ficticio /Home/UserDir/Documents directorio. Tan pronto como el usuario hace cualquier cambio, inotifywait emite la modificación y salida.
Suponiendo que cree un nuevo archivo llamado archivo nuevo dentro de Documentos carpeta mientras el inotifywait lo está monitoreando. Una vez que el comando detecta la creación de archivos, genera
Documentos/ crear newfile
En otras palabras, inotifywait Imprime donde ocurre la modificación, qué tipo de cambios realizó y el nombre del archivo o carpeta que se ha cambiado.
Examinar el estado de salida de inotifywait Cuando se realiza un cambio, ve un estado de 0-Exit que significa una ejecución exitosa. Esta situación es perfecta para un script de shell porque un estado de salida se puede usar como una condición verdadera o falsa.
En consecuencia, el primer paso del script está completo: encontrar una utilidad que espere cambios en los directorios. El segundo es buscar una utilidad capaz de sincronizar dos directorios, y rsync es un candidato perfecto.
Cómo usar RSYNC para Autobackups?
rsync es una aplicación poderosa. Puede escribir un libro que describe todo lo que puede hacer con esta utilidad versátil. Tecnicamente hablando, rsync no es nada más que una herramienta de cobertura de archivos, una especie de CP Comando con esteroides y poderes especiales como archivos de transferencia seguros. El uso de rsync en este guión es más modesto pero no menos elegante.
El objetivo principal es encontrar una manera de:
El rsync La documentación está bien escrita; Comprobando el resumen de las opciones disponibles, puede seleccionar fácilmente el -avz las banderas como la mejor opción. Un uso simple se ve de la siguiente manera:
rsync -avz/
Es importante poner un corte después de la carpeta de origen. De lo contrario, rsync Copia toda la carpeta de origen (incluida misma) a la carpeta de destino.
Por ejemplo, si crea dos carpetas, una llamada pliegue de origen y el otro carpeta de destino, para hacer rsync Envíe al segundo cada cambio realizado en el primero, use el comando posterior:
$ RSYNC -AVZ OrigenFolder/ DestinationFolder
Una vez que cree un nuevo archivo llamado archivo nuevo, rsync Imprime algo como:
Envío de la lista de archivos incrementales
./
archivo nuevo
enviado 101 bytes recibidos 38 bytes 278.00 bytes/seg
El tamaño total es 0 la aceleración es 0.00
En la primera línea, la Directiva imprime el tipo de proceso, una copia incremental; esto significa que el rsync Utiliza sus capacidades de compresiones para incrementar solo el archivo y no cambiar todo el archivo. Como es la primera vez que se ejecuta el comando, la aplicación copia todo el archivo; Una vez que ocurren nuevos cambios, solo se producen incrementos. La salida posterior es la ubicación, el nombre del archivo y los datos de rendimiento. Verificar el estado de salida del rsync Comando, recibe un 0-Exit para una ejecución exitosa.
Por lo tanto, hay dos aplicaciones importantes para brindar apoyo en este script: una es capaz de esperar cambios, y la otra puede crear copias de esta modificación en tiempo real. Aquí, lo que falta es una forma de conectar ambas utilidades de una manera que rsync toma medidas tan pronto como inotifywait percibe cualquier alteración.
Por qué necesitamos un bucle de tiempo?
La solución más simple para el problema anterior es un bucle de tiempo. En otras palabras, en cada ocasión inotifywait existe con éxito, el script bash debe llamar rsync para realizar su incremento; Inmediatamente después de que ocurra la copia, el shell debe volver al estado inicial y esperar una nueva salida del inotifywait dominio. Eso es exactamente lo que hace un bucle de tiempo.
No necesita una amplia experiencia en programación para escribir un script bash. Es muy común encontrar buenos administradores de sistemas que no tengan experiencia, o muy limitada, con la programación. Sin embargo, Crear scripts funcionales siempre es una tarea importante de administración del sistema. La buena noticia es que el concepto detrás de un bucle es fácil de entender.
El siguiente diagrama representa un bucle de tiempo:
Infinito mientras un diagrama de bucle.
A representa el inotifywait Comando discutido anteriormente y B, rsync. Cada vez A existe con un estado de 0-Exit, el shell lo interpreta como verdadero; Por lo tanto, el bucle While permite la ejecución de B; tan pronto B También sale correctamente, el comando vuelve a A de nuevo y repite el bucle.
En este caso, el bucle while siempre evalúa verdadero para A. Técnicamente, genera un bucle infinito, lo que es bueno para proponer este guión; inotifywait se ejecutará recurrentemente, lo que significa que siempre esperará nuevas modificaciones.
Más formalmente, la sintaxis para una fiesta, mientras que el bucle es:
mientras
hacer
hecho
significa la lista de condiciones (A) que necesita ser verdad; Entonces, el bucle de while puede ejecutar el , De pie para el bloque de comandos (B). Si el bucle previo a la prueba A es falso, entonces el bucle while sale sin ejecutar B.
Aquí es cómo rsync y inotifywait Los comandos encajan dentro del bucle While,
mientras inotifywait -r -e modifica, crea, elimina Origenfolder
hacer
RSYNC -AVZ OrigenFolder/ DestinationFolder
hecho
Combinando todo
Ahora es el momento de combinar todo lo que se discute anteriormente para crear un script de shell. Lo primero es crear un archivo vacío y nombrarlo; como ejemplo, vialbackup.intento representa una buena opción. Es una buena práctica colocar scripts de shell en la carpeta bin en el directorio de inicio del usuario, un.k.a. $ Inicio/Bin.
Después de eso, puede editar el archivo en el editor de texto de su elección. La primera línea de un script bash es muy importante; Aquí es donde el script define la directiva del intérprete, por ejemplo:
#! [Opciones]
El shebang es este símbolo extraño con un hash y un signo de exclamación (#!). Cuando el shell carga el script por primera vez, busca este signo, ya que indica qué intérprete debe usarse para ejecutar el programa. El shebang no es un comentario, y debe colocarse en la parte superior del guión sin espacios anteriores.
Puedes dejar la primera línea vacía y no definir el intérprete. De esta manera, el shell utiliza el intérprete predeterminado para cargar y ejecutar el script, sin embargo, no está respaldado. La opción más apropiada y segura es indicar la Directiva del intérprete de la siguiente manera:
#!/usr/bin/bash
Con la directiva de intérprete explícita como esa, el shell busca el intérprete bash bajo el directorio /usr /bin. Como la tarea de este script es simple, no es necesario especificar más comandos u opciones. Una posibilidad más sofisticada es llamar al intérprete utilizando el comando env enviado.
#!/usr/bin/envash
En este contexto, el shell busca el comando bash predeterminado en el entorno actual. Dicha disposición es útil cuando el entorno de usuario tiene personalizaciones importantes. Sin embargo, puede conducir a fallas de seguridad en un nivel empresarial una vez que el shell no puede detectar si la fiesta de comando en un entorno personalizado es o no un intérprete seguro.
Al armar todo en este punto, el guión se ve como:
#!/usr/bin/bash
mientras inotifywait -r -e modifica, crea, elimina OriginFolder
hacer
RSYNC -AVZ OrigenFolder/ DestinationFolder
hecho
Cómo usar argumentos en un script bash?
Lo que separa este script de una funcionalidad total es cómo está definiendo el origen y la carpeta de destino. Por ejemplo, es necesario encontrar una manera de mostrar cuáles son esas carpetas. El modo más rápido para resolver esa pregunta es usar argumentos y variables.
Aquí hay un ejemplo de la forma correcta de referirse al script:
ps ./LiveBackUp.Bash/Home/User/Origin/Home/User/Destino
El shell carga cualquiera de esos argumentos escrito después del nombre del script y los pasa al cargador de scripts como variables. Por ejemplo, el directorio /Inicio/Usuario/Origen es el primer argumento, y puede acceder a él dentro del script utilizando el $ 1. De este modo, $ 2 tiene un valor de /Inicio/Usuario/Destino. Se puede acceder a todas estas variables posicionales utilizando el signo de dólar ps seguido de un número n ($ N), donde n es la posición del argumento donde se llama el guión.
El signo de dólar ps tiene un significado muy especial e implicaciones dentro de los scripts de shell; En otros artículos, se discutirá en profundidad. Por ahora, el rompecabezas está casi resuelto.
#!/usr/bin/bash
mientras inotifywait -r -e modifica, crea, elimina $ 1
hacer
rsync -avz $ 1/ $ 2
hecho
Nota: Para lidiar con demasiados argumentos utilizando solo parámetros posicionales ($ N) puede conducir rápidamente a malos diseños y confusión en scripts de shell. Una forma más elegante de resolver ese problema es usar el getopts dominio. Este comando también lo ayuda a crear alertas sobre el uso de uso indebido, lo que puede ser útil cuando otros usuarios tienen acceso al script. Una búsqueda rápida en Internet puede mostrar diferentes métodos para usar getopts, ¿Qué puede mejorar el script actual si necesita dar más opciones de uso a otros usuarios?.
Haciéndolo ejecutable
Solo se debe hacer una cosa más ahora: para hacer el archivo vialbackup.intento ejecutable. Se puede realizar fácilmente con el chmod dominio.
Vaya a la carpeta que contiene el script y el tipo:
$ chmod +x LiveBackup.intento
Luego, escriba el letrero de piso de puntos (./) Antes del nombre del guión. El punto significa, en este contexto, el directorio actual y el corte define una ruta relativa al archivo en el directorio actual. Con esto en mente, también debe escribir la carpeta de origen como el primer argumento, seguido de la carpeta de destino como la segunda, como:
ps ./LiveBackUp.Bash/Home/User/Origin/Home/User/Destino
Alternativamente, puede llamar a los scripts por su nombre colocando su ubicación de carpeta en la ruta del entorno o llamarlo subshell, como:
$ Bash LiveBackup.Bash/Home/User/Origin/Home/User/Destino
Aunque la primera opción es una elección segura.
Ejemplo de la vida real
En un escenario del mundo real, ejecutar manualmente un script de copia de seguridad cada vez que inicie el sistema, puede ser tedioso. Una buena opción es usar un cronjob o temporizadores/servicio unidades con system. Si tiene muchas carpetas diferentes para hacer copias de seguridad, también puede crear otro script que obtenga el vialbackup.intento; Por lo tanto, el comando debe llamarse solo una vez en un .servicio unidad. En otro artículo, esta característica se puede discutir con más detalle.
Si está utilizando el subsistema de Windows para Linux, es posible crear una tarea básica para ejecutar su script utilizando el "Scheduler de tareas" que se desencadena por el inicio del sistema. Para usar un archivo por lotes para llamar al intento.exe con una lista de comandos es una buena opción. También puede usar un script de Visual Basic para iniciar el archivo por lotes en segundo plano.
Cómo se ve un guión de Pro Bash
Aquí hay un ejemplo de un script diseñado por el autor que puede leer argumentos de línea de comandos más sofisticados.
#!/usr/bin/envash
#
############################################## ####################################
############################################## ####################################
#
# Script: syncfolder.intento
# Autor: Diego Aurino da Silva
# Fecha: 16 de febrero de 2018
# Rev: 1.0
# Licencia: MIT (https: // github.com/diegoaurino/bashscripts/blob/maestro/licencia)
#
# Plataforma: WSL o GNU/Linux
#
# Propósito: Script pequeño para sincronizar los cambios de izquierda a derecha de dos carpetas
# bajo WSL o GNU/Linux (requiere herramientas inotify)
#
############################################## ####################################
############################################## ####################################
#################
# CONFIGURACIÓN GENERAL
#################
Bold = $ (Tput Bold)
Normal = $ (tput sgr0)
Origen = ""
destino = ""
#################
# Sección de opciones
#################
Si [$# -eq 0]
entonces
printf "\ n%s \ t \ t%s \ n \ n" "Usar $ bold -h $ normal para ayuda."
Salir 1
demás
Mientras que la opción Getopts ": H"
hacer
caso $ opción en
h)
printf "\ n%s \ t \ t%s \ n \ n" "Uso: ./carpeta de sincronización.Bash $ Bold/Origen/Folder $ Normal -o $ Bold/Destino/carpeta $ normal "
Salir 0
;;
\? )
printf "\ n%s \ n \ n" "$ Bold Opción no válida por $ normal $ (Basename $ 0)" 1> & 2
Salir 1
;;
ESAC
hecho
Shift $ ((optind -1))
Origen = $ 1
cambio
Mientras que Getopts ": O:" Opción
hacer
caso $ opción en
o)
destino = $ OPTARG
printf "\ n%s \ n \ n" "Las siguientes carpetas se sincronizarán a la izquierda:"
printf "\ torigen: \ t \ t \ t%s \ n" "$ bold $ Origen $ normal"
printf "\ tDestination: \ t \ t%s \ n \ n" "$ Bold $ Destino $ normal"
;;
\? )
printf "\ n%s \ n \ n" "$ Bold Opción no válida por $ normal $ (Basename $ 0): -$ Optarg."1> y 2
Salir 1
;;
:)
printf "\ n%s \ n \ n" "$ Bold La opción $ normal -$ Optarg requiere un directorio como argumento."1> y 2
Salir 1
;;
*)
printf "\ n%s \ n \ n" "$ Bold Opción Unkown por $ normal $ (Basename $ 0): -$ Optarg."1> y 2
Salir 1
;;
ESAC
hecho
Shift $ ((optind -1))
FI
#################
# Sección de sincronización
#################
mientras inotifywait -r -e modifica, crea, elimina $ Origen
hacer
RSYNC -AVZ $ Origen/ $ Destino --elete --filter = 'P .git '
hecho
Desafíos
Como desafío, intente diseñar dos versiones más del script actual. El primero necesita imprimir un archivo de registro que almacene cada cambio que se encuentran por el inotifywait comando y cada incremento realizada por rsync. El segundo desafío es crear un sistema de sincronización de dos direcciones utilizando solo un bucle de tiempo como el script anterior. Un pequeño consejo: es más fácil de lo que parece.
Puede compartir sus hallazgos o preguntas en Twitter @LinuxHint