Filed under codes

Maldito segmentation fault

Esse é um daqueles posts que serve mais para me ajudar, mas acho que pode ser útil para mais pessoas.
Já tive vários casos onde uma aplicação PHP gera um erro muito genérico nos logs do Apache, o famigerado “Segmentation fault”. Na prática significa que alguma coisa deu tão errado que o processo do Apache que estava executando o seu script PHP foi cancelado. Mas o log não ajuda muito, pois podem ser várias coisas.
Nesse post vou descrever o processo que fiz para encontrar um problema em uma aplicação. Os passos foram feitos em uma máquina virtual Ubuntu, a que eu gerei com o Vagrant.
O primeiro passo é instalar os pacotes necessários para conseguirmos toda a informação possível:

apt-get install libapr1-dbg libaprutil1-dbg gdb php5-dbg

Precisamos também configurar o Apache para que ele gere um “dump” com toda a informação do erro em um arquivo. No arquivo /etc/apache2/apache2.conf eu adicionei a seguinte linha:

CoreDumpDirectory /tmp/apache2-gdb-dump

Também precisamos criar o diretório e dar permissões para o Apache criar os arquivos:

mkdir /tmp/apache2-gdb-dump
chown -R www-data:www-data /tmp/apache2-gdb-dump

Após reiniciar o Apache é só executar novamente o script que está gerando o erro, e um arquivo será gerado no diretório criado, o /tmp/apache2-gdb-dump/core

Com esse arquivo podemos executar o gdb e verificar o que aconteceu com o programa. Precisamos executar:

gdb /usr/sbin/apache2 /tmp/apache2-gdb-dump/core

Será mostrado uma lista de ítens que o Apache executou. Para ver mais detalhe é só executar o comando

bt full

Analisando as mensagem é bem provável que você vai encontrar uma pista para o que exatamente está ocorrendo. No caso da minha aplicação que testei hoje o problema era na forma como estava carregando o arquivo .phar do Silex, conforme o que o gdb me mostrou:

#0  0x0112cefe in phar_get_archive (archive=0xbff5f87c, fname=0xb5dab6c4 "/vagrant/SOA-Server/vendor/silex.phar", fname_len=55, alias=0x213f323c "silex.phar", alias_len=10, error=0x0) at /build/buildd/php5-5.3.2/ext/phar/util.c:1255

Espero que esse post seja útil para mais alguém, e se você tiver outra receita de como desvendar esse tipo de problemas é só usar os comentários para dar a dica.

News feed usando nodeJS, Pubsub.io e jQuery

Um dos projetos que estamos desenvolvendo na Coderockr é uma rede social, da qual vamos dar mais detalhes no futuro, e um dos componentes é um news feed, algo parecido com o “mural do Facebook” onde são mostrados os eventos mais atuais aos usuários (novas notícias, novos pedidos de amizade, novos conteúdos, etc).
Estamos estudando algumas tecnologias para melhor solucionar esta necessidade, e uma das soluções é algo bem novo para nós, o uso quase que total de Javascript: nodeJS, Pubsub.io e nossa velha amiga jQuery.
O nodeJS é uma das tecnologias mais interessantes que surgiu nos últimos tempos. O mago do Javascript @jaydson escreveu alguns posts muito legais fazendo uma introdução e mostrando os primeiros passos na ferramenta. Recomendo a leitura.
O Pubsub.io é construído sobre o nodeJS e é um “query based message hub”, trabalhando com o conceito de publishers (programas que publicam conteúdo) e consumers (os que consumem as mensagens), e adicionando a possibilidade de usar uma query language baseada na usada pelo banco NoSQL MongoDB para filtrar os resultados.
A solução que estamos testando funciona da seguinte forma: sempre que um evento acontece (uma nova foto é salva, por exemplo) o componente que executou o evento (um model ou um controller de uma aplicação Zend Framework, por exemplo) faz uma requisição http para uma url servida pelo nodeJS e este publica uma mensagem no Pubsub.io. Na aplicação client, no navegador web, usando a biblioteca JS do Pubsub.io e o jQuery mostramos as mensagens na tela. Vamos tentar explicar com códigos :)
Após instalar o nodeJS e o npm (node packet manager) é preciso instalar o Pubsub.io, usando o comando abaixo, no mesmo diretório onde ficará o script server.js (script nodeJS mostrado abaixo):
npm install pubsub.io
Agora é preciso instalar e executar o servidor do Pubsub.io:

git clone git@github.com:pubsubio/pubsub-hub.git
./pubsub-hub/lib/server.js

Ele ficará ouvindo na porta 9999
O próximo passo é escrever o código do aplicativo do nodeJS e executá-lo com o comando:
node server.js
Como o nodeJS fica executando na porta 8080 podemos publicar novos eventos usando algo simples como um comando curl, via linha de comando:
curl -d "title=new photo&detail=http://localhost/photo/id/1&user=eminetto" http://127.0.0.1:8888
O -d indica que estamos usando o comando POST para enviar.
Podemos também usar o curl no PHP:

$url = 'http://127.0.0.1:8888';
$postvars = 'title=new image&detail=http://localhost/image/id/1&user=eminetto';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST ,1);
curl_setopt($ch, CURLOPT_POSTFIELDS ,$postvars);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,1);
curl_setopt($ch, CURLOPT_HEADER ,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,1);
$Rec_Data = curl_exec($ch);

Na parte client vamos usar a biblioteca Javascript do Pubsub.io e jQuery para mostrar ao usuário a notificação: ver código

No site do Pubsub.io é possível ver outras features importantes como a possibilidade de usar autenticação para garantir a segurança, queries avançadas e a possibilidade de usar o MongoDB para armazenar as mensagens.
Gostei muito da solução. Ainda falta testar coisas como performance, escalabilidade mas me parece ter um bom futuro.

Contabilizar espaço usado em FTP usando Python

Aqui na empresa temos duas contas de FTP contratadas no nosso plano de hospedagem para usarmos como espaço de backup. As duas contas tem um espaço limitado e toda semana eu preciso monitorar quanto espaço estamos usando, para evitar erros no script de backup. Para facilitar esse controle eu criei um pequeno script Python para navegar em todas as pastas e me dizer quanto espaço estou usando. O script ficou assim:

import os
from ftplib import FTP

def pretty_filesize(bytes):
	if bytes >= 1073741824:
		return str(bytes / 1024 / 1024 / 1024) + ' GB'
	elif bytes >= 1048576:
		return str(bytes / 1024 / 1024) + ' MB'
	elif bytes >= 1024:
		return str(bytes / 1024) + ' KB'
	elif bytes < 1024:
		return str(bytes) + ' bytes'

endereco_ftp = 'servidor'
usuario = 'usuario'
senha = 'senha'
conexao_ftp = FTP(endereco_ftp)

conexao_ftp.login(usuario,senha)
diretorio_corrente = conexao_ftp.pwd()
soma = 0
for i in conexao_ftp.nlst():
	conexao_ftp.cwd(i)
	for j in conexao_ftp.nlst():
		soma = soma + conexao_ftp.size(j)
	conexao_ftp.cwd('..')

print pretty_filesize(soma)

Agora é só colocar no crontab e receber diariamente o espaço utilizado.
Fontes:
http://www.vivaolinux.com.br/script/navegador-ftp
http://code.rivers.pro/python-function-to-convert-bytes-to-kbmbgb/

Enviando DMs do Twitter via shell script

Monitorar os servidores e serviços é uma tarefa importante para manter seus sites e sistemas sempre em ordem. Existem diversas ferramentas bem completas como o Nagios que fazem praticamente todo o serviço. Eu uso o Nagios para monitorar quase tudo e ele me avisa via e-mail de quaisquer problemas. O problema é que nã verifico e-mail o tempo todo.  Uma solução seria mandar os avisos via SMS, mas isso envolve alguns custos.

Nesse momento me lembrei do Twitter. Eu sou um daqueles viciados, que verifica o twitter diversas vezes por dia.  Pensando nisso fiz um pequeno script para monitorar o MySQL e caso o ping não responda eu recebo uma DM avisando.

Um exemplo do script:

status=`mysqladmin ping -hhost -uuser -psenha 2> /dev/null`
if [ "$status"  != "mysqld is alive" ]; then
   curl -u usuario_mon:senha -d "text=Erro conectando ao MySQL&user=eminetto" http://twitter.com/direct_messages/new.xml 2> /dev/null > /dev/null
fi
Um detalhe importante a lembrar é que não é bom usar sua conta no Twitter para enviar as DMs. O Twitter tem uma polí­tica que remove contas que usam muitas DMs por dia, temendo abuso e SPAM. O melhor é criar uma nova conta.  Além disso, é preciso que as duas contas sejam seguidoras uma da outra, senão a DM não pode ser enviada
Claro que eu poderia criar um plugin ou script para o próprio Nagios e deixar ele fazer isso para mim, mas assim ficou mais rápido. Além disso é só um exemplo

Material da palestra no PHPSC Conf 2009

Finalmente me organizei e fiz o upload dos slides da palestra que ministrei no PHPSC Conf 2009.
Coloquei no Slideshare. Se alguém precisar do arquivo em outro formato é só me avisar.
Melhorando a performance de aplicações com o uso do MemCache

Etiquetado , ,

Procura-se beta testers

Depois de alguns meses de desenvolvimento finalmente posso começar a comentar sobre o projeto que estou trabalhando. Chama-se Drimio.

Agora que estamos chegando perto do grande lançamento estamos recrutando beta testers para nos ajudar a aprimorar o serviço.  Então fica aqui o convite: SEJA UM DOS NOSSOS BETA TESTERS

Etiquetado

Lock em arquivos usando SVN e Subclipse

Outra novidade para mim ao usar o Subversion foi o controle de Locks. 

Eu sempre usei o CVS integrado ao Eclipse para gerenciar os projetos que eu trabalhava e com essa duplinha é bem fácil configurar para evitar que dois programadores alterem o mesmo arquivo.

Com o Subversion e o Eclipse (usando o plugin Subclipse) eu não encontrei essa opção. A solução que encontrei foi configurar o cliente do subversion para quando criar novos arquivos marcá-los com um flag. Este flag indica que, para editar o arquivo é preciso que seja feito o “lock” antes. No momento de criar o lock o Subclipse também verifica a versão do arquivo e avisa caso a versão local seja inferior a que consta no repositório. Desta forma eu garanto que o programador sempre tenha a última versão do arquivo e evito que duas pessoas alterem o mesmo arquivo ao mesmo tempo. Existem formas de corrigir isso usando práticas de merge, mas eu acho mais fácil evitar o problema do que resolvê-lo :-)

O que eu fiz foi alterar o arquivo config no diretório do usuário:

mate ~/.subversion/config

Eu estou usando o Textmate no MacOSX. Mas o mesmo passo vai funcionar no Linux. No Windows XP o arquivo encontra-se no diretório

c:\Documents and Settings\usuario\Dados de Aplicativos\Subversion\config

Neste arquivo eu alterei 

# enable-auto-props = yes

para

enable-auto-props = yes

E adicionei alinha abaixo na seção  [auto-props]

* = svn:needs-lock

Desta forma, assim que o programador criar um novo arquivo e realizar o primeiro commit é adicionada esta flag ao arquivo. Todos que forem alterá-lo vão passar pela fase “lock-edit-commit”, com um “update” caso seja necessário.

Etiquetado

Dicas de performance para scripts PHP

Excelente artigo com dicas de performance para scripts em PHP.

Vale a leitura

pyBovespa

Neste ano eu comecei a investir em ações. É algo ao mesmo tempo emocionante e apavorante porque você pode ganhar e perder dinheiro em questão de horas. Por isso é importante ficar sempre atento as alterações dos valores das ações. Existem vários programas e sites que permitem o acompanhamento das alterações. Mesmo assim, eu aproveitei a manhã de feriado, enquanto me recupero de uma pequena ressaca, e fiz um script em Python que busca os dados da Bovespa e permite o acompanhamento da sua “carteira de ações”. Assim dá para deixar um terminal aberto e ir acompanhando o mercado.
O script foi feito por diversão e uso pessoal, mas se servir para alguém mais legal. O código:

# -*- coding: utf-8 -*-
# Elton Luís Minetto
import urllib
from xml.dom import minidom
from time import sleep
from os import system

#adicionar as acoes aqui
#formato ACAO: [num_acoes,valor_compra,data_compra]
acoes = {
	'BBDC4':[100,34.84,'25/04/2008'],
	'PETR4':[100,42.00,'20/04/2008'],
}

def atualiza(acoes):
	system('clear')
	url = 'http://www.bovespa.com.br/Mercado/RendaVariavel/InfoPregao/ExecutaAcaoAjax.asp?CodigoPapel='
	for i in acoes:
		url += '|'+i
	f = urllib.urlopen(url)
	xml = f.read()
	xmldoc = minidom.parseString(xml)
	papeis = xmldoc.getElementsByTagName('Papel')
	#cabecalho
	print 'Ação\tValor de Compra\tData da Compra\tQtd\tAtual\tDiferença R$\tDiferença %\tData de Atualização'

	total_compra = 0.0
	total_dif_reais = 0.0
	for i in papeis:
		codigo = i.attributes['Codigo'].value
		valor_compra = acoes[codigo][1]
		qtd_acoes = acoes[codigo][0]
		data_compra = acoes[codigo][2]
		valor_atual = i.attributes['Ultimo'].value.replace(',','.')
		data_atual = i.attributes['Data'].value

		diferenca_reais = (float(valor_atual) * qtd_acoes) - (valor_compra * qtd_acoes)
		diferenca_perc = (diferenca_reais*100)/(valor_compra * qtd_acoes)
		total_compra += valor_compra * qtd_acoes
		total_dif_reais += diferenca_reais

		print '%s\t%02f\t%s\t%d\t%s\t%02f\t%02f\t%s' % (codigo,valor_compra,data_compra,qtd_acoes,valor_atual,diferenca_reais,diferenca_perc,data_atual)

	print 'Total de Compra:%02f' % total_compra
	print 'Total da Diferença em Reais:%02f' % total_dif_reais
	total_dif_perc = (total_dif_reais * 100)/total_compra
	print 'Total da Diferença em Percentual:%02f' % total_dif_perc
	sleep(1200)

while 1:
	atualiza(acoes)

Eu testei o script no MacOSX Leopard. Mas deve funcionar legal no Linux e no Windows
Download do arquivo

Etiquetado

Plugin para o WordPress fazer Highlight em fontes

Encontrei esse plugin para o WordPress que faz highlight em códigos nos posts:

http://wordpress.org/extend/plugins/highlight-source-pro/

Muito útil

Etiquetado
Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

Join 1.472 other followers