Sauvegarder votre site en utilisant git et Makefile

La traduction d'un site en un ensemble de pages Web statiques vous permet de réduire la charge sur le serveur ou même de profiter du stockage gratuit, ainsi que d'augmenter la fiabilité, la vitesse et la sécurité du site. Dans cet article, je vais vous expliquer comment procéder avec les outils familiers git et Makefile . Un avantage de cette approche est la possibilité de contrôler les versions du contenu des pages Web.


L'article décrit comment créer des versions statiques de pages Web pour l'émission de serveur et comment les placer dans un référentiel pour le contrôle de version et la sauvegarde. Dans le même temps, les fichiers statiques et multimédias peuvent être stockés séparément et archivés par d'autres moyens (les fichiers statiques sont généralement placés dans le référentiel du code de programme du site). La méthode fonctionne également pour les pages avec des noms Unicode (par exemple, pour les domaines cyrilliques). À la fin se trouve un Makefile fonctionnel.


L'auteur utilise la pile django / uwsgi / nginx, un serveur dédié virtuel exécutant GNU / Linux, mais le contenu de l'article est presque indépendant de technologies spécifiques.


Chargement des pages


Nous enregistrerons les pages du site à l'aide du programme wget standard. Nous enregistrerons chaque site dans un annuaire distinct (qui peut ne pas être associé au nom de domaine du site).


Dans chaque répertoire, les pages seront enregistrées de manière récursive à l' aide de la touche wget -r (on suppose que toutes les pages sont accessibles via des liens depuis la page principale). Par défaut, la copie récursive monte au niveau 5, mais cela peut être modifié à l'aide du commutateur -l .


Si nous stockons les fichiers multimédias et statiques séparément des pages de texte, les répertoires correspondants sont ignorés avec le commutateur -X .


La commande complète ressemble à ceci:


mkdir primer cd primer wget -r -nH -X ,static --restrict-file-names=nocontrol . 

-nH signifie --no -host-directory . Par défaut, wget -r example.com mettra tout dans le répertoire example.com/ , et cette option annule la création du répertoire avec le nom d'hôte.


L'option --restrict-file-names indique l'échappement de caractères dans l'URL lors de la création de fichiers locaux. Une valeur de nocontrol signifie la désactivation de l'échappement et est très importante pour enregistrer des pages avec des liens cyrilliques. Sans cela, les pages sont enregistrées dans des fichiers avec des noms légèrement modifiés, et il n'est pas tout à fait clair comment les envoyer au serveur. Malheureusement pour les utilisateurs de Windows, --restrict-file-names = nocontrol ne fonctionnera pas pour eux, il s'agit d'un problème connu.


Ajouter à git


Un nouveau référentiel est créé à l'aide de la commande git init . Par défaut, il est créé dans le répertoire courant du dossier .git, mais nous voulons que le serveur n'ait accès qu'aux fichiers qui correspondent aux noms des pages ouvertes du site. Par conséquent, la commande complète qui crée un référentiel propre (nu) dans le dossier ../.git-primer ressemble à ceci:


 git init --bare ../.git-primer 

Pour continuer à utiliser ce référentiel non standard, vous devez passer à git les options git-dir et work-tree :


 git --git-dir=../.git-primer --work-tree=. add . 

Écrire un Makefile


Commençons par l'annonce de nos projets:


 SITES := example primer all : $(SITES) .PHONY : $(SITES) 

La variable SITES contient les noms de nos projets. L'objectif par défaut est le premier objectif, tous , c'est-à-dire pour terminer toutes les étapes, il suffit de taper une commande make . Tous les objectifs dans SITES sont fictifs ( PHONY ): la recette de chacun d'eux sera exécutée indépendamment de l'existence du répertoire et de l'heure à laquelle il a été modifié.
L'introduction de base à faire peut être lue, par exemple, ici , et le guide de base est info make ( original , traduction ).


La règle pour chacun des projets ressemble à ceci:


 $(SITES) : if [[ -d .git-$@ ]]; \ then \ $(get-data); \ $(mgit) add . && \ if [[ -n "`$(mgit) status --porcelain`" ]]; then \ $(mgit) commit -m "Update $@."; \ fi \ else \ $(init-git); \ fi 

Cette règle est essentiellement une commande shell unique.
$ @ Est une variable automatique qui contient le nom de la cible actuelle (par exemple, amorce).
Nous vérifions d'abord si le répertoire .git-primer existe. Si oui, allez dans le répertoire du projet, téléchargez les pages, ajoutez-les à git.
Si le contenu des pages n'a pas changé, alors git n'ajoutera rien, mais dans ce cas, commit provoquera une erreur et l'exécution du Makefile s'arrêtera. Par conséquent, nous appelons d'abord git status avec l'option - porcelain , qui est destinée à être utilisée dans les scripts. Si la longueur de la ligne de sortie de git status --porcelain n'est pas nulle, alors nous pouvons faire un commit (à partir d'ici ).


get-data, mgit et init-git sont des recettes en conserve dans le Makefile. Par exemple, mgit est un appel git spécifiant un répertoire avec un référentiel et des fichiers de répertoire de travail:


 define mgit = git --git-dir=../.git-$@ --work-tree=. endef 

Les recettes en conserve sont créées lorsqu'une séquence de commandes peut être utilisée dans plusieurs recettes. Ils peuvent être constitués de plusieurs lignes, chacune étant automatiquement mise en évidence avec un onglet dans les recettes (plus précisément, avec le symbole .RECIPEPREFIX ). Dans notre exemple, l'indentation est faite uniquement pour la lisibilité du Makefile.
Lors de l'exécution des recettes, chaque ligne des séquences préparées est interprétée comme une ligne distincte de la recette, c'est-à-dire qu'elles peuvent notamment utiliser des variables automatiques à cet effet .


Le Makefile complet ressemble à ceci:


 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 

Dans le quatrième paragraphe, il y a des variables spécifiques à la cible : pour chaque objectif, vous pouvez définir votre propre valeur pour cette variable. Ces valeurs sont également transmises en fonction des prérequis de chacun des objectifs et des recettes préparées utilisées, c'est-à-dire que nous pouvons être sûrs que la recette de chaque site sera exécutée avec le nom de site correct et son répertoire.
Pour chaque projet, nous pouvons transférer nos répertoires non archivés via la variable EXCLUDEDIRS ou la laisser vide. De même, vous pouvez modifier le nom du serveur pour l'archivage à partir d'un ordinateur de travail ( SERVERHOST ) et le chemin d'accès sur le serveur vers le répertoire contenant l'archive du site ( SERVERPATH ). Par souci de simplicité, dans cet exemple, tous les sites sont sur le même serveur et archivés dans le même répertoire.
Étant donné que chaque ligne de la recette (y compris celle préparée) est exécutée dans un shell séparé, de sorte que la transition vers le répertoire reste valide pour les commandes suivantes, nous utilisons l'opérateur "et" && et échappons à la fin de la ligne \.


Vient ensuite la construction conditionnelle du Makefile: à l'aide de la commande shell hostname , nous vérifions si make s'exécute sur le serveur ou sur l'ordinateur local. Les lignes qui ne satisfont pas la branche actuelle de la directive conditionnelle sont complètement ignorées par le Makefile.


La différence entre les référentiels locaux et serveurs

L'ordinateur local est principalement utilisé pour stocker des données, nous ne copions donc que les données du serveur ( git pull ), et pour la commodité du travail local avec git (affichage des journaux ou des versions de fichiers), nous utilisons la structure de référentiel par défaut (le référentiel habituel dans le dossier .git )
Dans les deux cas, une seule commande make suffit. Pour la copie automatique, vous pouvez utiliser le planificateur cron . Afin de ne pas saisir à chaque fois le mot de passe d'accès au serveur, des clés ssh sont générées.


Pour faciliter le travail sur le serveur, vous pouvez créer un alias git à partir du répertoire du site actuel avec la configuration spécifiée:


 alias mgit="git --work-tree=. --git-dir=../.git-${PWD##*/}" 

La variable $ {PWD ## * /} contient le nom du répertoire courant sans chemin d'accès et fait partie de la norme POSIX , c'est-à-dire qu'il peut être utilisé dans tous les shells compatibles POSIX.


Une directive conditionnelle peut également être utilisée dans les recettes, la seule limitation étant que son début et sa fin ne peuvent pas être dans des fichiers différents.


Serveur

Après avoir exécuté make, le répertoire d'archives ressemble à ceci:


 $ ls -a . .. .git-example .git-primer Makefile example primer $ ls -a primer . .. index.html - - $ # ,     .    ./-  ./- 

Le fichier de configuration nginx pour example.rf pourrait ressembler à ceci:


 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; } } 

Le premier emplacement correspond à la page principale du site, example.rf. Il est enregistré par wget en tant que fichier index.html. Si ce n'est pas le cas, une erreur 404 est émise.


Pour tous les autres URI, les fichiers du répertoire d'amorce portant le nom URI sont vérifiés. S'ils ne sont pas trouvés, 404 est retourné.


En fin de compte, afin d'éviter la duplication de contenu, nous refusons explicitement l'accès au lien example.rf / index.html (404). Un peu plus de détails sur cette configuration est écrit ici .


Conclusion


La sauvegarde de sites peut être effectuée à l'aide des outils standard wget , git , make . Vous pouvez copier toutes les pages d'un site ou exclure des médias et un certain nombre d'autres fichiers aussi précisément que le permet wget . De même, avec .gitignore , vous pouvez contrôler quelles pages statiques seront ajoutées au référentiel pour la sauvegarde et lesquelles ne le seront pas. Makefile vous permet de gérer de manière flexible diverses configurations pour différents projets. Un exemple complet de Makefile pour le client et pour le serveur ci-dessus ne contient qu'environ 60 lignes.


Il est supposé que le changement et l'ajout de contenu de site se font par le biais de mécanismes standard, c'est-à-dire que CMS ou CMF est lancé pour cela. Si cela se produit rarement, après le travail, ils peuvent être désactivés, libérant ainsi des ressources système et affichant des pages statiques enregistrées. Un exemple d'automatisation plus complète peut mériter un article séparé.


La méthode proposée convient principalement aux petits projets qui sont rarement mis à jour, de sorte que les problèmes de performances et de sécurité ont été à peine examinés ici. Comme nous avons demandé à wget de ne pas échapper les caractères de l'URI, au cas où des utilisateurs arbitraires pourraient ajouter des fichiers au site, l'échappement ou l'interdiction de leur ajout devrait se produire immédiatement.


L'enregistrement des versions du contenu du site peut également être effectué via la base de données lors du changement de ses pages. Mais cela nécessite la prise en charge des versions par les modèles CMF, ainsi qu'un meilleur contrôle sur le vidage de la base de données (copiez-le entièrement après toute modification de page). Dans la méthode proposée, en cas de petite modification du contenu, seule cette modification sera ajoutée au référentiel, et l'utilisation d'une copie complète de la base de données n'est pas requise. De plus, les pages statiques générées peuvent être directement utilisées par le serveur ou affichées dans un navigateur (la modification de la conception ou d'un autre code de site sera également copiée).


D'autres programmes de sauvegarde sont répertoriés ici . Pour stocker et synchroniser des fichiers multimédias, vous devez faire attention à git-annex . La séparation du référentiel .git de l'arborescence de travail a également été utilisée avec succès pour gérer les fichiers de configuration utilisateur (fichiers dot ). Aujourd'hui, il existe des serveurs qui prennent directement en charge le travail avec les référentiels git.

Source: https://habr.com/ru/post/fr425259/


All Articles