Cleber J Santos
Posts do blog publicados pelo Cleber
Nginx, SPDY agora é real.
Já faz um tempo, postei aqui no Blog falando sobre o suporte ao módulo SPDY que estava próximo de ser real no Nginx, venho acompanhando o assunto desde 2012, a discussão e testes no Google e no chromium.
Após ler sobre o assunto e começar a ver que também o Nginx estava iniciando testes com um módulo que daria suporte ao protocolo me entusiasmei a também inciar testes, então após algum tempo, cá estou eu para finalizar o post. De fato ainda não é um protocolo muito usado, não é um módulo que todos os SysAdmin estão avaliando e usando, creio que por que não saberem, por ainda não ser tão bem divulgado, mas acredito que de fato este se torne um padrão para acelerar conexões SSL, dado que o Google já está usando como padrão no seu buscador.
Desde a versão 1.3.15 do Nginx já temos suporte não nativo do módulo, isso significa que podemos compilar o Nginx e habilitar o suporte ao SPDY desde que tenhamos os requerimentos para isso.
Para quem deseja instalar e começar a utilizar, aqui vai a dica de como fazer, antes de mais nada gostaria de reforçar que, infelizmente tanto o IE quanto o Safari não suportam SPDY. Você poderá verificar a tabela de compatibilidade para suporte de protocolo de rede SPDY em navegadores de desktop e móveis.
Requerimentos.
- libssl 1.0.1+.
- libpcre 3, libpcre3-dev.
- Compilador C (ex. GNU C Compiler)
- Navegador com suporte ao SPDY (ex. Google Chrome)
Garantindo que o sistema atenda os requisitos podemos seguir instalando o Nginx com o suporte ao módulo, então façamos:
$ cd /tmp $ wget http://nginx.org/download/nginx-1.4.2.tar.gz $ tar -xzf nginx-1.4.2.tar.gz
$ cd nginx-1.4.2 $ ./configure --with-http_spdy_module --with-http_ssl_module $ make $ sudo make install
server { listen 127.0.0.1:443 ssl spdy; server_name mysite.com; access_log logs/ssl-access.log; error_log logs/ssl-error.log; ssl_certificate ssl/mysite.crt; ssl_certificate_key ssl/mysite.key; ...
Para testar você pode instalar no Chrome ou no Firefox uma extensão.
Discutindo a relação com Varnish 3 e Plone 4
Pois é, já é a segunda vez que dou palestra e posto aqui falando sobre o tema, dessa vez pude palestrar no Plone Symposium, o encontro da comunidade sulamericana de Plone que este ano aconteceu em Brasília, no Auditório do Interlegis.
Vejo no assunto tratado pontos positivos e negativos, infelizmente pelo que pude perceber como ponto negativo é que muitos ainda desconhecem o Varnish, e pior, desconhecem o que é um cache, muitos já ouviram falar, mas não estão tão preocupados em saber se tem um servidor de cache por trás do site.
Alo interessante é que com o assunto Diazo em questão, todo o resto do Plone parece desnecessário :) pelo menos para mim é o que ficou muito visível, e isso é bom claro, apesar da minha palestra não ter a ver com o Diazo, o Plone por padrão não vem com suporte a ESI / SSI (Edge side includes / Server side include), dai minha citação sobre o Diazo.
"Hoje temos algumas formas que adicionar cache em partes de nosso site, isso mesmo, imagine você poder colocar um cache diferente para cada parte da sua Home, 5 minutos de cache em um portlet de imagens, 1 mês de cache para o rodapé do site, banners sem cache e assim vai."
Não quero escrever aqui toda a palestra então você pode assistir a palestra ou e também visualizar os slides abaixo.Suporte SPDY no Nginx se aproxima.
Recentemente um dos desenvolvedores do Nginx Valentin Bartenev, anunciou o suporte SPDY para o servidor web Nginx. SPDY (pronunciado speedy), trata-se de um protocolo de rede experimental desenvolvido essencialmente no Google para transporte de conteúdo web e focado em fazer a Web mais rápida.
Apesar de não ser atualmente um protocolo padrão, o grupo que está desenvolvendo o SPDY afirmou publicamente que está trabalhando em direção a uma padronização, e tem implementações de referência no momento disponíveis em ambos Google Chrome e Mozilla Firefox. O protocolo é similar ao HTTP, tendo como objetivo reduzir o tempo de carga de páginas da internet. Isso é conseguido priorizando e multiplexando a transferência dos sub-recursos da página web para que somente uma conexão por cliente seja necessária.
Encriptação TLS é praticamente onipresente nas implementações do SPDY, e a transmissões são comprimidas com gzip ou DEFLATE em contraste ao HTTP, em que os cabeçalhos não são comprimidos. Além disso, o servidor indica ou até mesmo envia conteúdo ao invés de esperar requisições individuais para cada recurso de uma página. O nome não é um sigla, mas um versão reduzida da palavra "speedy" do inglês.
Este trabalho foi patrocinado pela Automattic que desde 2008 utilizam Nginx e desde então tem feito parte de quase todas as peças de sua infra.
Desde 2011 a empresa já conversava com o pessoal da Nginx para fechar um acordo, onde a Automattic iria patrocinar o desenvolvimento e a integração do SPDY no Nginx, tendo como única exigência final que que o código resultante deva ser liberado sob uma licença de código aberto para que outros possam se beneficiar de todo o trabalho.
Já existem extensões para as versões recentes dos navegadores Google Chrome e Mozilla Firefox que permitem saber se um site já implementam o SPDY, visitando o próprio Google ou o Twitter já podemos perceber que utilizam o protocolo.
Andrew Alexeev – Nginx, Inc.
E melhor que usso, percebi que apenas este site https://barry.wordpress.com implementa o SPDY no Nginx, quando acessado através de SSL e que trata-se do blog de Barry, o atual chefe de sistemas Wrangler na Automattic e responsável pela execução da infra-estrutura distribuída globalmente, no qual deu nota e alguns detalhes da implementação do SPDY no Blog.
O futudo do SPDY será fazer parte da fonte oficial do servidor web Nginx, e confesso, estou ansioso para já testar tudo :) então nos próximos dias irei postar novidades sobre os testes, é claro que para quem desejar já testar pode já pegar os patches beta em http://goo.gl/SlaiA.
Para você que deseja também testar o SPDY com o Nginx, leia o link http://nginx.org/patches/spdy/README.txt.
Desvantagens
- O conteúdo enviado mesmo que já haja cache é um desperdício de banda.
- Softwares de filtragem que dependem do HTTP não funcionarão mais.
- Muito provável que o IE vai demorar para implementar o suporte a este protocolo.
Você sabia?
- O navegador Google Chrome e o Chromium já utilizam o SPDY quando se comunicam com os serviços do Google, como o Google Search, Gmail, Chrome sync e quando exibindo anúncios do Google. O Google reconhece que o uso do SPDY é habilitado em comunicações entre o Chrome e os servidores do Google que usam SSL.
- A partir da versão 11 do Mozilla Firefox e SeaMonkey V2.8 existe o suporte a SPDY, apesar de não ser habilitado por padrão. O suporte pode ser habilitado através da preferencia network.http.spdy.enabled preference em about:config.
- No Firefox 13 o SPDY é habilitado por padrão.
- Também no Google Chrome há um parâmetro de linha de comando (--enable-websocket-over-spdy) que habilita uma implementação experimental do WebSocket sobre SPDY.
- E também podemos utilizar o Google Chrome para inspecionar as sessões do SPDY, acessando uma URL especial:
chrome://net-internals/#events&q=type:SPDY_SESSION%20is:active
Python: Google and April Fool's Day
Como bem sabemos o dia da mentira é comemorado por todos e por muitas empresas, até mesmo o Google entrou nessa, e este ano não foi diferente, porém o que venho postar não é sobre o dia da mentira ou sobre as brincadeiras que o Google tem feito, apesar de serem muito divertidas.
O que me chamou a atenção foi o tal do Elegantizr que foi divulgado como um framework que promete deixar o site até 3 vezes mais rápido, e pior, muita gente mesmo caiu nessa!
Risadas a parte, a brincadeira foi tão legal que logo eu quis saber como foi feita. É bem provável que muitos venham a dizer que é algo super simples e etc, porém vale ainda assim blogar.
A brincadeira.
<link rel="stylesheet" href="http://www.google.com/landing/elegantizr/elegantizr.css" />
:before { content: '\41\50\52\49\4C\20\46\4F\4F\4C\20\F4\BF\F4'; }
a:link:before { content: " (" attr(href) ") "; }
Depois do texto de um link.
a:link:after { content: " (" attr(href) ") "; }
Como fazer.
'\41\50\52\49\4C\20\46\4F\4F\4C\20\F4\BF\F4'
>>> text = 'APRIL FOOL ô¿ô' >>> text.encode('hex').upper() '415052494C20464F4F4C20C3B4C2BFC3B4'
>>> text = 'APRIL FOOL ô¿ô' >>> text.encode('iso-8859-1').encode('hex').upper() '415052494C20464F4F4C20F4BFF4'
'\41\50\52\49\4C\20\46\4F\4F\4C\20\F4\BF\F4'
>>> text = 'Python' >>> text.encode('iso-8859-1').encode('hex').upper() '507974686F6E'
O Css.
:before { content: '\50\79\74\68\6F\6E'; }
Até a próxima.
JavaScript Minify com Python
Trabalhando em um projeto recentemente precisei gerar um arquivo menor do jQuery que eu havia modificado, e com isso comecei a me perguntar como o jquery.com o fazia com seus arquivos por exemplo:
- jquery-1.7.1.js 244K
- jquery-1.7.1.min.js 92K
$ mkdir cobaia $ curl -O http://code.jquery.com/jquery-1.4.4.js $ ls -hs *.js
$ easy_install jsmin
$ pip install jsmin
$ python
>>> from os import path >>> from os.path import join >>> >>> # Usei o cStringIO por ser mais rápido que o StringIO implementado em Python >>> from cStringIO import StringIO >>> >>> # As linha abaixo é o que nos garante o uso do jsmin >>> import jsmin >>> jmin = jsmin.JavascriptMinify() >>> >>> base = path.dirname(path.abspath(path.realpath(__name__))) >>> >>> # Abrimos o arquivo original apenas como leitura >>> filejs = open(join(base, 'jquery-1.4.4.js'),'r') >>> >>> # Pegamos o nome do arquivo original e concatenamos com .min.js >>> filename_out = str(str(filejs.name.split('/')[-1]).split('.js')[0] + '.min.js') >>> >>> file_out = StringIO() >>> file_out.write("") >>> >>> # Gerando um novo arquivo com modo de escrita >>> file_out = open(join(base, filename_out),'wb') >>> >>> # Por fim passamos para o minify um arquivo de entrada e o de saída >>> jmin.minify(filejs,file_out) >>> file_out.close()
$ ls -hs *.js
Outra forma de fazer.
$ gcc jsmin.c -o jsmin $ ./jsmin < jquery-1.4.4.js > jquery-1.4.4.min.js
O pulo do gato.
Varnish 3, Plone 4: Discutindo a Relação.
Não preciso dizer o quanto a PythonBrasil [7] foi um sucesso :-D , infelizmente não tive como ver todas as palestras o que seria bizarro conseguir, dado que não sou onipresente. Apesar da minha palestra ter sido em uma sexta-feira no final do dia eu pude extrapolar o tempo, e ainda ficou faltando diversos detalhes.
Um detalhe importante é que o @ericof apareceu e também participou da palestra, conhecidencia ou não, ocorreu após eu ter invocado seu nome 3 vezes. Em minha apresentação pude mostrar o quanto o Varnish é poderoso, e o quanto a combinação Varnish [3] e Plone [4] pode ser igual a [42].
VMODs: O lego do Varnish 3
VMODs, ou simplesmente Varnish Modules é, segundo da documentação de modificações, um dos grandes sucessos obtidos na versão 3: "VMODs on the other hand, was an instant success, because they make it much easier for people to extend Varnish with new functionality".
E realmente, é o mesmo que tenho achado, como bem sabemos desde o Varnish 2.1 podemos usar C inline para criar e estender funcionalidades que por padrão o Varnish não trás, e com a chegada dos módulos essa brincadeira tona-se ainda melhor, por tudo que podemos fazer na VCL.
Sabermos ainda que existem coisas que não temos como fazer na VCL, por exemplo: Procurar um número de IP em um arquivo de banco de dados. Usando código C inline até temos como resolver este problema, já que o Varnish nos provê isso, e lá você pode fazer tudo, mas não é uma forma conveniente ou mesmo legível para resolver tais problemas. Eis o lugar onde VMODs entram em cena.
O que é a VMOD?
Trata-se de uma biblioteca compartilhada com algumas funções C que pode ser chamado a partir do código VCL.
A interface entre o VMOD o compilador VCL ("VCC") e o tempo de execução VCL ("VRT") é definido em um arquivo de nome vmod.vcc que um script python de nome "vmod.py" que faz todo o trabalho duro
Executando o vmod.py no arquivo vmod.vcc, será produzido dois arquivos, que são: "vcc_if.c" e "vcc_if.h", no qual devemos usar para construir o nosso arquivo de biblioteca compartilhada.
o vcc_if.c até pode ser esquecido em nosso VMOD, mas o vcc_if.h é importante, ele contém os protótipos para as funções que desejamos exportar para a VCL.
vmod_dir Default: ${VARNISH:DIR}/lib/varnish/vmods
Na prática.
- 1º Exemplo.
import example; sub vcl_deliver { # Vamos definit o resp.http.hello para "Hello, World" set resp.http.hello = example.hello("World"); }
- 2º Exemplo
Módulo: https://github.com/leed25d/geoip-vmod
Autor: David Newhall
Descrição: Provê a capacidade de retornar a localização geográfica de um endereço IP.
Nota: Após instalar o módulo (como instalar em README) basta executar o seguinte trecho de código em sua VCL.
import geoip;
sub vcl_recv {
# Definimos um cabeçalho de solicitação X-GeoIP
# para o geo do solicitante (ou desconhecido).
set req.http.X-Forwarded-For = client.ip;
set req.http.X-GeoIP = geoip.country(req.http.X-Forwarded-For)
}
- 3º Exemplo
Autor: Tollef Fog Heen
Descrião: Este vmod é um dos que mais gosto, ele provê o curls para o Varnish, então podemos usar o varnish como um cliente HTTP e buscar cabeçalhos e corpo nos backends.
Nota: Após instalar o módulo (como instalar em README) basta executar o seguinte trecho de código em sua VCL.
import curl; sub vcl_recv { curl.fetch("http://example.com/test"); if (curl.header("X-Foo") == "bar") { … } curl.free(); }
Um pouco mais antes de terminar.
- Adicionando o std.collect(), coletamos vários cabeçalhos HTTP para um único cabeçalho.
import std; sub vcl_recv { std.collect(req.http.foo); } sub vcl_fetch { std.collect(beresp.http.bar); }
- Retornando uma URL em caixa alta ou uma string.
sub vcl_deliver { set resp.http.foo = std.toupper(req.url); }
set beresp.http.x-scream = std.toupper("yes!");
- Retorna o contrário do toupper, ou seja, strings todas em caixa baixa.
set beresp.http.x-nice = std.tolower("VerY");
Ainda temos random, log, set_up_tos, syslog, fileread, duration e integer, no qual adoraria escrever sobre, mas fica a dica para quem desejar conhecer, o VMOD é realmente uma verdadeira caixa de legos, e o mais legal é que você ainda pode criar novas peças e encaixar nas já existentes. Espero que tenha sido u bom post para você entender e começar a montar a sua VMOD, e espero que post aqui sobre a experiência.
Até a próxima.
Leia também:
Migrando Varnish 2.1 para Varnish 3.0
Nas últimas semanas tenho tido a oportunidade de ficar mais próximo do Varnish, e nas últimas três semanas comecei a migrar do varnish 2.1 para Varnish 3, posso dizer desde já que teve um grande salto de melhorias e também de implementações. Mas neste post irei tratar apenas de como preparar sua configuração de vcl para não ser pego de supresa quando fazer um upgrade da versão.
O exemplo de vcl a seguir foi retirado do svn do Varnish: https://www.varnish-cache.org/trac/browser/etc/zope-plone.vcl e será com base neste vcl que iremos efetuar a migração.
Breve resumo das mudanças de 2.1.5 para 3.0.0
- Suporte ao módulo VMODs [3].
- Suporte a Compressão e descompressão, incluindo compressão de fragmentos ESI.
- Suporte a carregamento preliminar de streaming, tanto em cache ou não.
- Melhor documentação.
- Melhor valores padrão para parâmetros.
- varnishncsa agora com suporte de log com formatos personalizado.
- varnishlog, varnishncsa e varnishhist agora com suporte a filtros de registros que correspondem múltiplas expressões.
Alterações na VCL.
- log foi movido para o vmod std.[4]
log "Olá mundo";
import std; std.log "Olá mundo";
- purge agora torna-se o chamadas ban, ou como dito na VCL, são funções ban.
purge(“req.url = ” req.url);
ban(“req.url = ” + req.url);
purge continua existindo porém não leva nenhum argumento mais, e ainda pode ser usado em vcl_hit ou vcl_miss para fazer purge de itens do cache, onde você iria reduzir o ttl a 0 no Varnish 2.1.
sub vcl_hit { if (req.request == “PURGE”) { set obj.ttl = 0s; error 200 “Purged.”; } }
sub vcl_hit { if (req.request == “PURGE”) { purge; error 200 “Purged.”; } }
- beresp.cacheable está fora.
beresp.cacheable está fora do Varnish 3, mas pode ser substituído por beresp.ttl> 0s
- returns agora é feito com a função return()
pass, pipe, lookup, deliver, fetch, hash, pipe e restart não são mais palavras-chave, mas argumentos para a função return(), então:
sub vcl_pass { pass; }
torna-se
sub vcl_pass { return(pass); }
- req.hash foi substituído por hash_data()
set req.hash += req.url;
hash_data(req.url);
- esi substituído por beresp.do_esi
esi;
set beresp.do_esi = true;
pass em vcl_fetch foi renomeado para hit_for_pass
A diferença no comportamento do pass em vcl_recv e vcl_fetch confundem as pessoas, apenas para torna mais claro as coisas, eles são diferentes :) e agora devemos usar return(hit_for_pass) onde usava-se pass no vcl_fetch.
- NOTA.
O Varnish 3 também teve uma mudança de comportamento, isso significa que ele irá retornar um erro quando cabeçalhos forem muito grandes ao em vez de apenas ignorá-los. E se os limites são muito baixos, retornará HTTP 413, então deve-se alterar limits por http_req_hdr_len e http_req_size. Essas alterações devem ser feitas em tempo de execução, o que significa adicionar como parâmetro do executável varnishd, exemplo (-p http_req_hdr_len=4096 -p http_req_size=1024).
Para maiores informações sobre parâmetros em tempo de execução acesse a documentação[5].
Migrando.
Eis aqui nosso exemplo retirado do svn do Varnish, porém convertido para a versão 3.0, retirei quais quer comentários da VCL e efetuei a migração, acredito que depois da explicação dos parâmetros acima você seja capaz de migrar a sua configuração.
backend default { .host = "127.0.0.1"; .port = "9673"; } acl purge { "localhost"; "192.0.2.0"/24; } sub vcl_recv { if (req.http.host ~ "(www.)?example.com") { set req.http.host = "example.com"; set req.url = regsub(req.url, "^", "/VirtualHostBase/http/example.com:80/example.com/VirtualHostRoot"); } elsif (req.http.host ~ "(www.)?example.org") { set req.http.host = "example.org"; set req.url = regsub(req.url, "^", "/VirtualHostBase/http/example.org:80/example.org/VirtualHostRoot"); } else { error 404 "Unknown virtual host."; } if (req.request != "GET" && req.request != "HEAD") { if (req.request == "POST") { return(pass); } if (req.request == "PURGE") { if (!client.ip ~ purge) { error 405 "Not allowed."; } return(lookup); } } if (req.http.Cookie && req.http.Cookie ~ "__ac(|_(name|password|persistent))=") { if (req.url ~ "\.(js|css)") { remove req.http.cookie; return(lookup); } return(pass); } } sub vcl_hit { if (req.request == "PURGE") { purge; error 200 "Purged"; } } sub vcl_miss { if (req.request == "PURGE") { error 404 "Not in cache"; } } sub vcl_fetch { if (beresp.ttl < 3600s) { set beresp.ttl = 3600s; } }
Indicação de leitura.
Plone 4, velocidade e Chameleon tudo em comum.
Num post anterior escrito pelo amigo simplificador @Tamosauskas (Plone mais rápido com Chameleon), foi mencionado a preocupação e empenho que a comunidade Plone tem tido quando o assunto é desempenho. Pois bem, neste post pretendo reforçar este aspecto, lembrando que essa é umas das preocupações da comunidade, tenho também como maior delas a segurança é claro.
Como dito no post do @Tamosauskas, a cada nova versão do Plone percebemos um ganho de desempenho, desde a versão 2.5 até a mais atual em desenvolvimento 4.1rc3 (Atual até a data que estou escrevendo este post), e claro, ganho de novas funcionalidades mudanças significativas para criação de novos produtos e tipos e a mudança da skin padrão.
O que exatamente é o tal do Chameleon?
Ele usa a linguagem do Page Template, só que sua implementação é bem mais rápida e independente, no qual trás um conjunto de novos recursos e podemos usar em qualquer aplicação escrita em Python (2.5 e superior, incluindo 3.x e PyPy), algumas de suas características são:
- Rápido - Os templates são compilados para byte-code.
- Extensível - É fácil de estender uma linguagem ou criar sua própria.
- Testado - Testes automatizados que protege contra regressões.
Usando Chameleon no seu buildout.
eggs = ... five.pt>=2.1zcml = ... five.pt
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:i18n="http://xml.zope.org/namespaces/i18n" lang="en" metal:use-macro="context/main_template/macros/master" i18n:domain="plone"> <body> <metal:main fill-slot="main" tal:define="name string:world"> Hello ${name}! </metal:main> </body> </html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:i18n="http://xml.zope.org/namespaces/i18n" lang="en" metal:use-macro="context/main_template/macros/master" i18n:domain="plone"> <body> <metal:main fill-slot="main"> <div tal:replace="python:'here==context:'+str(here==context)" /> <div tal:replace="python:'here==container:'+str(here==container)" /> <div tal:replace="string:root:${root/getPhysicalPath}" /> <div tal:replace="string:nothing:${nothing}" /> <div tal:define="cgi python:modules['cgi']" tal:replace="python: dir(cgi)" /> </metal:main> </body> </html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:i18n="http://xml.zope.org/namespaces/i18n" lang="en" metal:use-macro="context/main_template/macros/master" i18n:domain="plone"> <body> <metal:main fill-slot="main"> <table border="1"> <tr tal:repeat="row python:['apple', 'banana', 'pineapple']"> <td tal:repeat="col python:['juice', 'muffin', 'pie']"> ${row/capitalize} ${col} </td> </tr> </table> </metal:main> </body> </html>
Buildout, para o que der e vier Parte 2
O buildout.
[buildout] parts = ... supervisor nginx-build nginxctl default-server-config ... [nginx-build] recipe = zc.recipe.cmmi url = http://nginx.org/download/nginx-1.0.4.tar.gz extra_options = --with-http_gzip_static_module --with-http_stub_status_module --with-http_dav_module --with-http_ssl_module --with-http_flv_module --http-client-body-temp-path=${buildout:directory}/tmp --http-proxy-temp-path=${buildout:directory}/tmp/proxy --http-fastcgi-temp-path=${buildout:directory}/tmp/fastcgi --with-md5-asm --with-md5=/usr/include --with-sha1-asm --with-sha1=/usr/include --with-http_realip_module [nginxctl] recipe = gocept.nginx nginx = nginx configuration = daemon off; worker_processes 1; events { worker_connections 1024; } http { include ${nginx:location}/conf/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; include ${buildout:directory}/etc/nginx.conf; } [default-server-config] recipe = collective.recipe.template input = ${buildout:directory}/etc/nginx.conf.in output = ${buildout:directory}/etc/nginx.conf [supervisor] recipe = collective.recipe.supervisor logfile = ${buildout:directory}/var/log/supervisord.log logfile-backups = 10 loglevel = info pidfile = ${buildout:directory}/var/supervisord.pid plugins = superlance user = admin password = secret port = 9001 programs = 10 fcgi ${buildout:directory}/parts/fcgi/bin/spawn-fcgi [ -a 127.0.0.1 -p 53217 -P ${buildout:directory}/tmp/fastcgi-php.pid -- /usr/bin/php-cgi] true 20 nginx ${buildout:directory}/parts/nginxctl/sbin/nginx [ -c ${buildout:directory}/parts/nginxctl/nginxctl.conf] true
Então crie estes dois diretórios e vamos seguir em frente, também teremos que criar dentro do diretório etc um arquivo com o nome nginx.conf, este contém as configurações para rodar-mos o WP, abaixo o conteúdo deste arquivo.
server { listen 80; server_name *.meusite.com; rewrite ^ http://www.meusite.com$request_uri permanent; } server { location / { root /home/cleber/buildout/wordpress; index index.php index.html index.htm; fastcgi_index index.php; # this sends all non-existing file or directory requests to index.php if (!-e $request_filename) { rewrite ^(.+)$ /index.php?q=$1 last; } autoindex on; } location = /favicon.ico { empty_gif; log_not_found off; access_log off; } # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac). location ~ /\. { deny all; access_log off; log_not_found off; } try_files $uri $uri/ /index.php; location ~ \.php$ { include /home/cleber/buildout/parts/nginx-build/conf/fastcgi_params.default; fastcgi_pass 127.0.0.1:53217; fastcgi_param SCRIPT_FILENAME /home/cleber/buildout/wordpress/$fastcgi_script_name; } }
./bin/supervisord
Nota. Vale lembrar que a porta 80 só pode ser aberta pelo root ou por um usuário com poder igual, neste caso estamos falando que o comando acima deverá ser rodado por um usuário com poderes de sudo ou root.
Até a próxima!
Buildout, para o que der e vier
Começo dizendo que durante algum tempo fui assombrado pelo buildout, desde a minha entrada na Simples até alguns meses depois, eu tremia sempre que eu tinha de rodar um, a primeira coisa que vinha na cabeça era: "Pronto, agora o ambiente vai ser destruído :(".
Trabalhar com alho no pescoço, pé de coelho e até mesmo trevo de 4 folhas não estava em meu escopo de trabalho, e não é muito meu tipo, pois bem, depois de algumas brigas decidi me tornar o melhor amigo do buildout, após alguns copos de café, e saindo juntos, decidimos fazer as pazes.
Hoje posso garantir, que em qualquer situação onde preciso instalar alguma aplicação que vá ou não rodar com o Plone, penso no meu amigo buildout.
Duas pessoas que me tiraram esse medo e me deram coragem foi o amigo e inesquecível Dorneles, e também o amigo Érico.
E agora a novidade é que não vou falar de como instalar Plone usando buildout, isso tudo para poder mostrar todo o poder do buildout, caso não saiba ainda do que estou falando acesso em http://www.buildout.org/docs/tutorial.html.
Buildout
- É simples de usar e de manter se você fizer configurações simples e legíveis.
- Trabalha com eggs.
- Evita conflitos com os pacotes instalados no site_packages.
- Evita a instalação diretamente no Python do sistema.
- Instala dependências a partir das definições dos eggs.
- Podemos instalar por exemplo:
- Bancos de dados: PostgreSql, Mysql, Oracle e etc...
- Serviço de autenticação como o LDAP.
- Aplicações como: Versões diferentes de Python, Varnish,Squid, Supervisor e etc..
- Frameworks: Django, Web2Py, Zope
- CMS: Plone, WordPress e etc..
- Servidores web: Apache, Nginx e etc...
- E etc...
|- tmp|- etc|- src
Instalando o WordPress usando Python, ironia?
[buildout] parts = fcgi wp [wpconf] wpversion = latest.tar.gz mydb_name = wp mydb_user = wp mydb_pass = wpnginx mydb_charset = utf8 mydb_host = localhost [downloads] wp_url = http://wordpress.org/${wpconf:wpversion} fcgi_url = http://www.lighttpd.net/download/spawn-fcgi-1.6.3.tar.gz [ports] fastcgi = 53217 [fcgi] recipe = zc.recipe.cmmi url = ${downloads:fcgi_url} configure-options = --prefix=${buildout:directory}/parts/fcgi [wp] recipe = plone.recipe.command command = chmod 600 .installed.cfg if [ ! -f ${buildout:directory}/${wpconf:wpversion} ]; then wget ${downloads:wp_url}; fi tar xzf ${wpconf:wpversion} cp ${buildout:directory}/wordpress/wp-config-sample.php ${buildout:directory}/wordpress/wp-config.php ln -dfs ${buildout:directory}/wordpress ${buildout:directory}/var/www/wordpress sed -i "s/define('DB_NAME', 'database_name_here')/define('DB_NAME', '${wpconf:mydb_name}')/" ${buildout:directory}/wordpress/wp-config.php sed -i "s/define('DB_USER', 'username_here')/define('DB_USER', '${wpconf:mydb_user}')/" ${buildout:directory}/wordpress/wp-config.php sed -i "s/define('DB_PASSWORD', 'password_here')/define('DB_PASSWORD', '${wpconf:mydb_pass}')/" ${buildout:directory}/wordpress/wp-config.php sed -i "s/define('DB_HOST', 'localhost')/define('DB_HOST', '${wpconf:mydb_host}')/" ${buildout:directory}/wordpress/wp-config.php sed -i "s/define('DB_CHARSET', 'utf8')/define('DB_CHARSET', '${wpconf:mydb_charset}')/" ${buildout:directory}/wordpress/wp-config.php chmod +x ${buildout:directory}/bin/spawn-fcgi update-command = ${wp:command
Criei duas seções que servirá para instalar o WordPress e um script de inicialização do php-cgi, este script também vem quando instalamos o servidor lighttpd, que é uma forma de manter o php vivo enquanto podemos dar um restart ou reload no servidor lighttpd, mas isso não vem ao caso.
Também criamos 3 outras seções que são:
wpconf - > Colocamos aqui as configurações do nosso WP, como dados da base de dados [usuário, senha etc ] e a versão que desejamos instalar do WP.
downloads -> Urls das aplicações, WP e fcgi.
ports -> Configuração da porta no qual o fcgi irá rodar
Note que na seção [wp], usei alguns comandos para fazer a mágica acontecer, quero baixar e descompactar o tar.gz, lembrando que em casos de arquivos zip, será necessário alterar a linha. Após descompactar copiamos o arquivo wp-config-sample.php para wp-config.php, este será o que o Wp irá ler.
E por fim, setamos os dados de acesso ao bando de dados neste arquivo de configuração.
Rode o bootstrap e o buildout: python bootstrap.py && ./bin/buildout -Nvvv -t 30
Ao final teremos o o Wp instalado e pronto pra usar, é claro que faltam detalhes como instalar o servidor Apache ou Nginx, ou um de sua preferência.
Para subir o fcgi você pode executar:
./parts/fcgi/bin/spawn-fcgi -a 127.0.0.1 -p 53217 -P ./tmp/fastcgi-php.pid -- /usr/bin/php-cgi
A configuração acima, usei com o servidor Nginx, também compilado com buildout, por este motivo adicionei o fcgi, abaixo sugestões de eggs que ajudam nas instalações.
Sugestões.
- zc.recipe.cmmi: Usado para executar comando configure/make/make install
- plone.recipe.command: Executa comandos arbitrários para o buildout.
- collective.recipe.supervisor: Receita para instalar o supervisor
- z3c.recipe.usercrontab: Adicionar comandos ao Crontab do Linux
- collective.recipe.template: Receita para a criação de templates de configurações
- Mais :)
Botões para compartilhar nas redes sociais.
Cada vez mais tem crescido o número de redes sociais, e claro não tem melhor maneira de divulgar e compartilhar posts do seu Blog e notícias do seu WebSite ou portal se não através dessas redes. Você já deve ter visto em outros sites, botões para compartilhar posts nas principais redes sociais, como Twitter e Facebook.
Existem diversos produtos que proporciona funcionalidades de compartilhamento para essas redes, e dentre estes vou falar de dois que são:
Ambos os produtos nos proporcionam recursos de compartilhamento de conteúdos do nosso site Plone, porém cada qual tem sua caracteristica, o sc.social.like é um produto mais simples que após instalado irá provê os botões para compartilhamento do Twitter e Facebook, estes botões ficam localizados logo abaixo do título do conteúdo em questão.
Tendo uma interface de configuração no qual pode-se alternar entre os botões recomendar e Curtir do Facebook, e as disposições vertical ou horizontal de ambos os botões, assim como configurações para quais tipos de conteúdos serão exibidos.
Enquanto o sc.social.bookmarks mostra-se como um produto mais completo, provendo um número maior de redes sociais para compartilhamento como Delicious, Digg, Reddit e Twitter e etc... Sendo 62 serviços já inclusos, ao contrário do sc.social.like, ele se dispõe no roda pé do conteúdo.Também é configurável, no qual pode-se escolher em para quais tipos de conteúdos será exibido.
Qual devo usar?
Como dito, cada qual tem suas caracteristicas, ainda que pareçam servir para o mesmo propósito, temos aqui um produto mais simples e outro mais completo, cabe a você escolher qual usar, o bookmarks não tem por exemplo um contador como no caso dos botões do like, neste caso para sites que desejam mostrar e também saber quantas vezes foram compartilhados determinado conteúdo de seu site, é mais recomendado o uso do like.
Agora para sites que apenas querem disponibilizar aos seus usuários um maior número de redes para que possam compartilhar, fica a recomendação o uso do bookmarks, ou ainda pode-se utilizar ambos, e aproveitar o que cada qual dispõe. Seja qual for a sua escolha, estes são produtos que acredito serem essenciais em um site.
O sabor de diversas versões Python para Linux e OSX usando o collective.buildout.python
Aproveitando a onda dos Buildouts, agora você pode instalar versões do interpretador Python (2.4, 2.5, 2.6, 2.7 e 3.1) no sistema *UNIX ou OSX, e assim melhor trabalhar com seus projetos de Buildout sem medo de ser feliz.