La traducción de un sitio a un conjunto de páginas web estáticas le permite reducir la carga en el servidor o incluso aprovechar el almacenamiento gratuito, así como aumentar la confiabilidad, velocidad y seguridad del sitio. En este artículo, hablaré sobre cómo hacer esto con las herramientas conocidas de git y Makefile . Una ventaja de este enfoque es la capacidad de controlar las versiones del contenido de la página web.
El artículo describe cómo hacer versiones estáticas de páginas web para la emisión del servidor y cómo colocarlas en un repositorio para control de versiones y copia de seguridad. Al mismo tiempo, los archivos estáticos y multimedia pueden almacenarse por separado y archivarse por otros medios (la estática generalmente se coloca en el repositorio del código de programa del sitio). El método también funciona para páginas con nombres Unicode (por ejemplo, para dominios cirílicos). Al final hay un Makefile que funciona.
El autor utiliza la pila django / uwsgi / nginx, un servidor virtual dedicado que ejecuta GNU / Linux, pero el contenido del artículo es casi independiente de tecnologías específicas.
Cargando páginas
Guardaremos las páginas del sitio utilizando el programa wget estándar. Guardaremos cada sitio en un directorio separado (que puede no estar asociado con el nombre de dominio del sitio).
Dentro de cada directorio, las páginas se guardarán de forma recursiva utilizando la tecla wget -r (se supone que se puede acceder a todas las páginas a través de enlaces desde la página principal). Por defecto, la copia recursiva sube al nivel 5, pero esto se puede cambiar con el modificador -l .
Si almacenamos archivos multimedia y estáticos por separado de las páginas de texto, los directorios correspondientes se ignoran con el modificador -X .
El comando completo se ve así:
mkdir primer cd primer wget -r -nH -X ,static --restrict-file-names=nocontrol .
-nH significa --no-host-directorios . De forma predeterminada, wget -r example.com pondrá todo en el directorio example.com/ , y esta opción cancela la creación del directorio con el nombre del host.
La opción --restrict-file-names indica el escape de caracteres en la URL al crear archivos locales. Un valor de nocontrol significa deshabilitar el escape y es muy importante para guardar páginas con enlaces cirílicos. Sin ella, las páginas se guardan en archivos con nombres ligeramente modificados, y no está del todo claro cómo emitirlas al servidor. Desafortunadamente para los usuarios de Windows, --restrict-file-names = nocontrol no funcionará para ellos, este es un problema conocido.
Añadir a git
Se crea un nuevo repositorio utilizando el comando git init . Por defecto, se crea dentro del directorio actual en la carpeta .git, sin embargo, queremos que el servidor solo tenga acceso a los archivos que corresponden a los nombres de las páginas abiertas del sitio. Por lo tanto, el comando completo que crea un repositorio limpio (desnudo) en la carpeta ../.git-primer se ve así:
git init --bare ../.git-primer
Para seguir utilizando este repositorio no estándar, debe pasar git las opciones git-dir y work-tree :
git --git-dir=../.git-primer --work-tree=. add .
Escribiendo un Makefile
Comencemos con el anuncio de nuestros proyectos:
SITES := example primer all : $(SITES) .PHONY : $(SITES)
La variable SITES contiene los nombres de nuestros proyectos. El objetivo predeterminado es el primer objetivo, todos , es decir, para completar todos los pasos, simplemente escriba un comando make . Todos los objetivos en SITIOS son ficticios ( FALSIA ): la receta para cada uno de ellos se ejecutará independientemente de la existencia del directorio y la hora en que se modificó.
La introducción básica a make se puede leer, por ejemplo, aquí , y la guía básica es info make ( original , traducción ).
La regla para cada uno de los proyectos se ve así:
$(SITES) : if [[ -d .git-$@ ]]; \ then \ $(get-data); \ $(mgit) add . && \ if [[ -n "`$(mgit) status --porcelain`" ]]; then \ $(mgit) commit -m "Update $@."; \ fi \ else \ $(init-git); \ fi
Esta regla es esencialmente un comando de shell único.
$ @ Es una variable automática que contiene el nombre del objetivo actual (por ejemplo, primer).
Primero verificamos si existe el directorio .git-primer. Si es así, vaya al directorio del proyecto, descargue las páginas, agréguelas a git.
Si el contenido de las páginas no ha cambiado, entonces git no agregará nada, pero en este caso, commit causará un error y la ejecución del Makefile se detendrá. Por lo tanto, primero llamamos al estado de git con la opción - porcelana , que está diseñada para usarse en scripts. Si la longitud de la línea de salida del estado de git --porcelana no es cero, entonces podemos hacer commit ( desde aquí ).
get-data, mgit e init-git son recetas enlatadas en el Makefile. Por ejemplo, mgit es una llamada a git que especifica un directorio con repositorio y archivos de directorio de trabajo:
define mgit = git --git-dir=../.git-$@ --work-tree=. endef
Las recetas enlatadas se crean cuando una secuencia de comandos se puede usar en varias recetas. Pueden constar de varias líneas, cada una de las cuales se resalta automáticamente con una pestaña en las recetas (más precisamente, con el símbolo .RECIPEPREFIX ). En nuestro ejemplo, la sangría se realiza solo para facilitar la lectura del Makefile.
Durante la ejecución de las recetas, cada línea de las secuencias preparadas se interpreta como una línea separada de la receta, es decir, en particular, pueden usar variables automáticas para este propósito .
El Makefile completo se ve así:
SITES := primer example SERVERHOST := example # . punicode SERVERHOSTNAME := xn--e1afmkfd.xn--p1ai SERVERPATH := ~/archive all : $(SITES) .PHONY : $(SITES) # target-specific variables primer : DOMAIN := . primer : EXCLUDEDIRS := ,static example : DOMAIN := example.com ifeq ($(SERVERHOSTNAME),$(shell hostname)) # Server define mgit = git --git-dir=../.git-$@ --work-tree=. endef define init-git = mkdir -p $@ && \ $(get-data) && \ git init --bare ../.git-$@ && \ $(mgit) add . && \ $(mgit) commit -m "Initial commit of $@." endef define get-data = cd $@ && \ wget -r -nH -X $(EXCLUDEDIRS) --restrict-file-names=nocontrol $(DOMAIN) endef else # Workstation define init-git = git clone $(SERVERHOST):$(SERVERPATH)/.git-$@ $@ endef endif $(SITES) : ifeq ($(SERVERHOSTNAME),$(shell hostname)) # Server if [[ -d .git-$@ ]]; \ then \ $(get-data); \ $(mgit) add . && \ if [[ -n "`$(mgit) status --porcelain`" ]]; then \ $(mgit) commit -m "Update $@."; \ fi \ else \ $(init-git); \ fi else # Workstation if [[ -d $@/.git ]]; \ then \ cd $@ && git pull; \ else \ $(init-git); \ fi endif
En el cuarto párrafo hay variables específicas del objetivo : para cada objetivo, puede establecer su propio valor para esta variable. Estos valores también se transmiten en función de los requisitos previos de cada uno de los objetivos y las recetas preparadas utilizadas, es decir, podemos estar seguros de que la receta de cada sitio se ejecutará con el nombre correcto del sitio y su directorio.
Para cada proyecto, podemos transferir nuestros directorios no archivados a través de la variable EXCLUDEDIRS o dejarlo vacío. Del mismo modo, puede cambiar el nombre del servidor para archivar desde una computadora que funciona ( SERVERHOST ) y la ruta del servidor al directorio con el archivo del sitio ( SERVERPATH ). Para simplificar, en este ejemplo, todos los sitios están en el mismo servidor y archivados en el mismo directorio.
Como cada línea de la receta (incluida la preparada) se ejecuta en un shell separado, de modo que la transición al directorio sigue siendo válida para los siguientes comandos, usamos el operador "y" && y escapamos al final de la línea \.
Lo siguiente es la construcción condicional de Makefile: usando el comando shell hostname , verificamos si make se ejecuta en el servidor o en la computadora local. El Makefile ignora completamente las líneas que no satisfacen la rama actual de la directiva condicional.
La diferencia entre repositorios locales y de servidorLa computadora local se usa principalmente para almacenar datos, por lo que solo copiamos datos del servidor ( git pull ), y para la conveniencia de trabajar localmente con git (ver registros o versiones de archivos) usamos la estructura de repositorio predeterminada (el repositorio habitual en la carpeta .git )
En ambos casos, un solo comando make es suficiente. Para la copia automática, puede usar el programador cron . Para no ingresar la contraseña para acceder al servidor cada vez, se generan claves ssh.
Para la conveniencia de trabajar en el servidor, puede crear un git de alias desde el directorio del sitio actual con la configuración especificada:
alias mgit="git --work-tree=. --git-dir=../.git-${PWD##*/}"
La variable $ {PWD ## * /} contiene el nombre del directorio actual sin una ruta y es parte del estándar POSIX , es decir, se puede usar en todos los shells habilitados para POSIX.
Una directiva condicional también se puede usar en recetas, la única limitación es que su principio y fin no pueden estar en archivos diferentes.
ServidorDespués de ejecutar make, el directorio de archivo se ve así:
$ ls -a . .. .git-example .git-primer Makefile example primer $ ls -a primer . .. index.html - - $
El archivo de configuración nginx por ejemplo.rf podría verse así:
server { server_name xn--e1afmkfd.xn--p1ai; charset utf-8; location = / { root /home/user/archive/primer; try_files /index.html =404; } location / { root /home/user/archive/primer; default_type "text/html"; try_files $uri =404; } location = /index.html { return 404; } }
La primera ubicación corresponde a la página principal del sitio, ejemplo.rf. Wget lo guarda como un archivo index.html. Si no es así, se emite un error 404.
Para todos los demás URI, se verifican los archivos en el directorio de cebador con el nombre URI. Si no se encuentran, se devuelve 404.
Al final, para evitar la duplicación de contenido, denegamos explícitamente el acceso al enlace example.rf / index.html (404). Aquí se escribe un poco más de detalle sobre esta configuración.
Conclusión
La copia de seguridad de los sitios se puede hacer usando las herramientas estándar wget , git , make . Puede copiar todas las páginas de un sitio o excluir medios y una cantidad de otros archivos con la precisión que permite wget . Del mismo modo, con .gitignore , puede controlar qué páginas estáticas se agregarán al repositorio para la copia de seguridad y cuáles no. Makefile le permite administrar de manera flexible varias configuraciones para varios proyectos. Un ejemplo completo de Makefile para el cliente y para el servidor anterior contiene solo unas 60 líneas.
Se supone que el cambio y la adición del contenido del sitio ocurre a través de mecanismos estándar, es decir, se lanza CMS o CMF para esto. Si esto ocurre raramente, entonces, después del trabajo, pueden apagarse, liberando recursos del sistema y mostrando páginas estáticas guardadas. Un ejemplo de automatización más completa puede merecer un artículo separado.
El método propuesto es principalmente adecuado para proyectos pequeños que rara vez se actualizan, por lo que aquí no se consideraron los problemas de rendimiento y seguridad. Dado que le indicamos a wget que no escape caracteres del URI, en caso de que los usuarios arbitrarios puedan agregar archivos al sitio, debe producirse el escape o la prohibición de su adición de inmediato.
Guardar versiones del contenido del sitio también se puede hacer a través de la base de datos al cambiar sus páginas. Pero esto requiere soporte de versión por modelos CMF, así como un mayor control sobre el volcado de la base de datos (cópielo completamente después de cualquier edición de página). En el método propuesto, en caso de un pequeño cambio en el contenido, solo este cambio se agregará al repositorio, y no se requiere el uso de una copia completa de la base de datos. Además, las páginas estáticas generadas pueden ser utilizadas directamente por el servidor o visualizadas en un navegador (también se copiará el cambio de diseño u otro código del sitio).
Los programas alternativos de respaldo se enumeran aquí . Para almacenar y sincronizar archivos multimedia, debe prestar atención a git-annex . La separación del repositorio .git del árbol de trabajo también se ha utilizado con éxito para administrar los archivos de configuración del usuario (archivos de puntos ). Hoy en día hay servidores que admiten directamente trabajar con repositorios git.