A tradução de um site em um conjunto de páginas estáticas da Web permite reduzir a carga no servidor ou até mesmo aproveitar o armazenamento gratuito, além de aumentar a confiabilidade, velocidade e segurança do site. Neste artigo, falarei sobre como fazer isso com as ferramentas familiares git e Makefile . Uma vantagem dessa abordagem é a capacidade de controlar versões do conteúdo da página da web.
O artigo descreve como criar versões estáticas de páginas da Web para emissão do servidor e como colocá-las em um repositório para controle e backup de versão. Ao mesmo tempo, os arquivos estáticos e de mídia podem ser armazenados separadamente e arquivados por outros meios (a estática geralmente é colocada no repositório para o código do programa do site). O método também funciona para páginas com nomes Unicode (por exemplo, para domínios cirílicos). No final, há um Makefile em funcionamento.
O autor usa a pilha django / uwsgi / nginx, um servidor virtual dedicado executando o GNU / Linux, mas o conteúdo do artigo é quase independente de tecnologias específicas.
Carregando páginas
Salvaremos as páginas do site usando o programa wget padrão. Salvaremos cada site em um diretório separado (que pode não estar associado ao nome de domínio do site).
Dentro de cada diretório, as páginas serão salvas recursivamente usando a tecla wget -r (pressupõe-se que todas as páginas possam ser acessadas através de links da página principal). Por padrão, a cópia recursiva sobe para o nível 5, mas isso pode ser alterado usando a opção -l .
Se armazenarmos mídia e arquivos estáticos separadamente das páginas de texto, os diretórios correspondentes serão ignorados com a opção -X .
O comando completo é assim:
mkdir primer cd primer wget -r -nH -X ,static --restrict-file-names=nocontrol .
-nH significa - sem diretórios host . Por padrão, o wget -r example.com colocará tudo no diretório example.com/ e essa opção cancela a criação do diretório com o nome do host.
A opção --restrict-file-names indica a fuga de caracteres no URL ao criar arquivos locais. Um valor de nocontrol significa desativar a fuga e é muito importante para salvar páginas com links cirílicos. Sem ele, as páginas são salvas em arquivos com nomes ligeiramente alterados e não está totalmente claro como enviá-las ao servidor. Infelizmente para usuários do Windows, --restrict-file-names = nocontrol não funcionará para eles, esse é um problema conhecido.
Adicionar ao git
Um novo repositório é criado usando o comando git init . Por padrão, ele é criado dentro do diretório atual na pasta .git, no entanto, queremos que o servidor tenha apenas acesso aos arquivos que correspondem aos nomes das páginas abertas do site. Portanto, o comando completo que cria um repositório limpo (vazio) na pasta ../.git-primer é semelhante a este:
git init --bare ../.git-primer
Para usar ainda mais esse repositório não padrão, você precisa passar ao git as opções git-dir e work-tree :
git --git-dir=../.git-primer --work-tree=. add .
Escrevendo um Makefile
Vamos começar com o anúncio de nossos projetos:
SITES := example primer all : $(SITES) .PHONY : $(SITES)
A variável SITES contém os nomes de nossos projetos. O objetivo padrão é o primeiro objetivo, para concluir todas as etapas, basta digitar um comando make . Todos os objetivos no SITES são fictícios ( PHONY ): a receita de cada um deles será executada independentemente da existência do diretório e da hora em que ele foi alterado.
A introdução básica a fazer pode ser lida, por exemplo, aqui , e o guia básico é info make ( original , tradução ).
A regra para cada um dos projetos é assim:
$(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 regra é essencialmente um único comando shell.
$ @ É uma variável automática que contém o nome do destino atual (por exemplo, iniciador).
Primeiro, verificamos se o diretório .git-primer existe. Nesse caso, vá para o diretório do projeto, faça o download das páginas e adicione-as ao git.
Se o conteúdo das páginas não mudou, o git não adicionará nada, mas, neste caso, o commit causará um erro e a execução do Makefile será interrompida. Portanto, primeiro chamamos status de git com a opção porcelain , que se destina ao uso em scripts. Se o comprimento da linha de saída do status git --porcelain não for zero, poderemos confirmar (a partir daqui ).
get-data, mgit e init-git são receitas enlatadas no Makefile. Por exemplo, mgit é uma chamada git que especifica um diretório com os repositórios e os arquivos do diretório de trabalho:
define mgit = git --git-dir=../.git-$@ --work-tree=. endef
As receitas enlatadas são criadas quando uma sequência de comandos pode ser usada em várias receitas. Eles podem consistir em várias linhas, cada uma das quais é destacada automaticamente com uma guia nas receitas (mais precisamente, com o símbolo .RECIPEPREFIX ). No nosso exemplo, o recuo é feito apenas para facilitar a leitura do Makefile.
Durante a execução das receitas, cada linha das seqüências preparadas é interpretada como uma linha separada da receita, ou seja, em particular, elas podem usar variáveis automáticas para esse fim .
O Makefile completo é assim:
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
No quarto parágrafo, existem variáveis específicas de destino : para cada objetivo, você pode definir seu próprio valor para essa variável. Esses valores também são transmitidos dependendo dos pré - requisitos de cada uma das metas e das receitas preparadas utilizadas, ou seja, podemos ter certeza de que a receita de cada site será executada com o nome do site correto e seu diretório.
Para cada projeto, podemos transferir nossos diretórios não arquivados através da variável EXCLUDEDIRS ou deixá-lo em branco. Da mesma forma, você pode alterar o nome do servidor para arquivamento de um computador em funcionamento ( SERVERHOST ) e o caminho no servidor para o diretório com o arquivo do site ( SERVERPATH ). Para simplificar, neste exemplo, todos os sites estão no mesmo servidor e arquivados no mesmo diretório.
Como cada linha da receita (incluindo a preparada) é executada em um shell separado, para que a transição para o diretório permaneça válida para os seguintes comandos, usamos o operador "and" && e escapamos do final da linha \.
A seguir, está a construção Makefile condicional : usando o comando shell hostname , verificamos se make é executado no servidor ou no computador local. Linhas que não satisfazem o ramo atual da diretiva condicional são completamente ignoradas pelo Makefile.
A diferença entre repositórios locais e de servidorO computador local é usado principalmente para armazenar dados, portanto, apenas copiamos dados do servidor ( git pull ) para ele e, para a conveniência do trabalho local com git (exibindo logs ou versões de arquivos), usamos a estrutura de repositório padrão (o repositório usual na pasta .git )
Nos dois casos, um único comando make é suficiente. Para cópia automática, você pode usar o agendador cron . Para não inserir a senha de acesso ao servidor toda vez, chaves ssh são geradas.
Para facilitar o trabalho no servidor, você pode criar um alias git a partir do diretório do site atual com a configuração especificada:
alias mgit="git --work-tree=. --git-dir=../.git-${PWD##*/}"
A variável $ {PWD ## * /} contém o nome do diretório atual sem um caminho para ele e faz parte do padrão POSIX , ou seja, pode ser usada em todos os shells habilitados para POSIX.
Uma diretiva condicional também pode ser usada em receitas, a única limitação é que seu início e fim não podem estar em arquivos diferentes.
ServidorApós executar o make, o diretório de arquivamento fica assim:
$ ls -a . .. .git-example .git-primer Makefile example primer $ ls -a primer . .. index.html - - $
O arquivo de configuração nginx, por exemplo.rf, pode se parecer com o seguinte:
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; } }
O primeiro local corresponde à página principal do site, example.rf. Ele é salvo pelo wget como um arquivo index.html. Caso contrário, é emitido um erro 404.
Para todos os outros URIs, os arquivos no diretório do iniciador com o nome URI são verificados. Se eles não forem encontrados, 404 será retornado.
No final, para evitar duplicação de conteúdo, negamos explicitamente o acesso ao link example.rf / index.html (404). Um pouco mais de detalhes sobre essa configuração está escrito aqui .
Conclusão
O backup de sites pode ser feito usando as ferramentas padrão wget , git , make . Você pode copiar todas as páginas de um site ou excluir a mídia e vários outros arquivos com a precisão que o wget permitir. Da mesma forma, com .gitignore , você pode controlar quais páginas estáticas serão adicionadas ao repositório para backup e quais não. Makefile permite gerenciar de forma flexível várias configurações para vários projetos. Um exemplo completo do Makefile para o cliente e o servidor acima contém apenas cerca de 60 linhas.
Supõe-se que a alteração e a adição do conteúdo do site ocorram através de mecanismos padrão, ou seja, o CMS ou o CMF é lançado para isso. Se isso acontecer raramente, depois do trabalho, eles podem ser desativados, liberando recursos do sistema e exibindo páginas estáticas salvas. Um exemplo de automação mais completa pode merecer um artigo separado.
O método proposto é adequado principalmente para pequenos projetos que raramente são atualizados; portanto, problemas de desempenho e segurança quase não foram considerados aqui. Como instruímos o wget a não escapar caracteres do URI, no caso de usuários arbitrários poderem adicionar arquivos ao site, a fuga ou a proibição de sua adição deve ocorrer imediatamente.
Também é possível salvar versões do conteúdo do site através do banco de dados ao alterar suas páginas. Mas isso requer suporte de versão dos modelos CMF, além de maior controle sobre o despejo do banco de dados (copie-o completamente após qualquer edição da página). No método proposto, no caso de uma pequena alteração no conteúdo, apenas essa alteração será adicionada ao repositório, e o uso de uma cópia completa do banco de dados não será necessário. Além disso, as páginas estáticas geradas podem ser usadas diretamente pelo servidor ou visualizadas em um navegador (a alteração do design ou outro código do site também será copiada).
Programas alternativos de backup estão listados aqui . Para armazenar e sincronizar arquivos de mídia, você deve prestar atenção ao git-anexo . A separação do repositório .git da árvore de trabalho também foi usada com êxito para gerenciar arquivos de configuração do usuário (arquivos de ponto ). Hoje existem servidores que suportam diretamente o trabalho com repositórios git.