terça-feira, 29 de maio de 2007

O Linux vai ao Internet Banking

Guardião Internet 30 horas UnibancoO Unibanco adotou, a partir desta semana, um novo mecanismo de segurança para acesso ao seu Internet Banking. O problema, já mencionado pelo PSL Brasil, é que ele parece ser incompatível com o Linux.

Neste post eu comento o que me levou a abrir uma conta no Unibanco e uma forma de burlar o tal mecanismo e continuar acessando normalmente o sistema, a partir do bom e velho Linux.

O interessante é ressaltar que um dos seus concorrentes, o Banrisul, caminha na direção contrária. Ele também passou a exigir recentemente a instalação de um dispositivo adicional de segurança. Porém, essa exigência é destinada apenas a quem utiliza o Windows (qualquer versão dele), como escreveu o Dirceu Follmann, de forma bem humorada.

No início do ano passado recebi uma correspondência do Unibanco, nela estava escrito que eu havia sido selecionado para abrir um conta-corrente livre de taxas. O que já parecia suspeito, ficou ainda mais difícil de acreditar ao ler o segundo parágrafo, que afirmava que eles iriam fazer um depósito inicial de R$ 50,00 caso alguma despesa mensal (luz/telefone/...) fosse registrada como débito em conta.

Como o Unibanco já havia enviado dois cartões de crédito (Mastercard/Visa) sem anuidades para o resto da vida e com limite de R$ 3500,00, sem que eu precisasse fazer absolutamente nada, exceto aceitar, mas ainda com os dois pés atrás, decidi ir até a agência mais próxima. Falei com o pessoal de lá, li e reli o contrato. Acabei abrindo uma conta e cadastrei a fatura da companhia de energia elétrica como débito em conta.

Hoje, R$ 50,00 e quinze meses depois, ao tentar acessar o Internet Banking, me deparei com o que parecia inevitável. O tal do mecanismo de segurança precisa ser obrigatoriamente instalado. Caso ele não estiver instalado, a mesma tela exigindo a instalação é exibida.

Depois de tentar desinstalar e reinstalar o plugin no Firefox por meia dúzia de vezes eu já estava quase desistindo de tentar fazê-lo funcionar. Foi quando eu descobri o que acredito ser um pequeno descuido da equipe que implantou o novo mecanismo e que permite o uso normalmente, mesmo usando o Linux.

As instruções são as seguintes:

  • na tela que possui o botão 'Instalar', clique nele para disparar a instalação do plugin;
  • vai abrir uma nova janela, solicitando a confirmação da instalação do plugin no Firefox;
  • nessa tela, clique em 'Cancelar';
  • vai aparecer o selo que ilustra este post, onde está escrito 'Guardião Internet 30 horas não instalado';
  • ignore isso, daqui para frente o acesso funciona normalmente, ou seja, clique no seu nome, forneça a senha e faça o que você precisa fazer.

Não sei por quanto tempo essa forma alternativa de acesso estará funcionando, mas tudo indica que nem o próprio pessoal do Unibanco sabe disso ainda. Afinal, a recomendação oficial para resolver o problema é passar a usar o Windows... claro e na 'bunada não vai dinha'... ;-)

Atualização: o André já havia comentado que a dica funcionava apenas parcialmente, mas provavelmente em função das reclamações da comunidade Linux[1, 2, 3, 4], desde a última sexta-feira, dia 8 de junho, a instalação do tal dispositivo adicional de segurança não é mais necessário para quem acessa o Internet Banking pelo Linux. Ponto para nós... ;-)

Leia mais...

quinta-feira, 24 de maio de 2007

Comandos mais usados e algumas dicas

Ok, eu admito... eu não resisto a um meme... :-D

Desta vez o assunto[1, 2, 3] é referente aos comandos mais executados na sua máquina...

Porém eu acabei sendo um pouco mais abrangente, falando de coisas que podem ser úteis no seu dia a dia.

Originalmente a idéia seria apenas postar o resultado desta seqüência de comandos (a contra-barra foi usada apenas para não quebrar o layout do blog, que tem uma largura fixa limitada):

history|awk '{print $2}'|awk 'BEGIN {FS="|"} {print $1}'|\
        sort|uniq -c|sort -rn|head -10

Eu até tenho uma simpatia muito grande pelo bash (apesar de querer muito aprender o zsh) e pelo demais comandos utilizados, mas tenho algum tipo de aversão ao awk (e, diga-se de passagem, não tem nada a ver com o Aho, o livro do dragão continua na minha relação dos favoritos). Desculpe-me, mas eu realmente não gosto dele. Deve ser alguma influência do Verde, mas eu prefiro o sed. É um direito meu... ;-)

Buenas, com o amado sed, o comando simplifica um pouco (isso se você, como eu, gosta de comer expressões regulares com farinha...):

history|sed -r 's/[ 0-9]+ ([^ |]+).*/\1/'|\
        sort|uniq -c|sort -rn|head -10

Explicando um pouco a regexp: ela ignora todos os espaços ou números seguido de um espaço, casa com uma seqüência de caracteres até encontrar o próximo espaço ou uma barra vertical (vulgo pipe), ignorando todo o resto.

Para eu não ser crucificado por aí, esta é uma versão pythônica da coisa:

from os.path import expanduser

history = open(expanduser('~/.bash_history'))
commands = [line.split()[0].split('|')[0] for line in history]
counter = {}
for command in commands:
    if command in counter:
        counter[command] += 1
    else:
        counter[command] = 1

topten = sorted(counter.items(), key=lambda x:x[1], reverse=True)
for command, total in topten[:10]:
    print total, command

Não usei nada de extraordinário para resolver o problema, apenas limpei os comandos que estavam armazenados no histórico e salvei numa lista. Depois criei um dicionário cuja chave era o comando e o valor era o número de vezes que o comando ocorreu. Em seguida, ordenei de forma reversa a lista de tuplas de itens do dicionário, considerando a segunda posição (o total de ocorrências) como chave de ordenação. Por fim, imprimi os comandos com os respectivos totais.

Certo, agora para acabar a enrolação aqui vai a minha relação atual:

1378 vi
 713 sudo
 372 ls
 327 svn
 267 cd
 214 python
 133 mv
  88 ssh
  68 rgrep
  64 less

Com base nela você fica sabendo qual o meu editor, paginador e linguagem de programação preferidos, que eu evito ficar logado como root, que eu uso um sistema de controle de versões, que eu acesso outras máquinas de forma segura, que eu procuro em arquivos de forma recursiva, além de verificar a listagem e mudar de diretório de vez em quando. A última coisa a ser dita é que o mv só faz parte da lista porque toda semana tem episódios novos das séries[1, 2] que eu acompanho (que por sinal acabaram juntas nessa semana...) e eu movo os arquivos para o pendrive para poder assistir no DVD player da sala, com som 5.1... ;-)

Para quem estranhou a quantidade de comandos armazenados no meu histórico, basta dizer que o meu ~/.bashrc está configurado para armazenar os 5000 últimos comandos, sem repetição seqüencial e sem salvar os que iniciam com um espaço em branco (útil para aqueles que não devem ficar armazenados):

export HISTCONTROL=ignoreboth
export HISTSIZE=5000

Por fim, ainda utilizo o seguinte ~/.inputrc, de forma a ignorar maiúsculas/minúsculas quando usar a tecla tab para completar nomes de arquivos/diretórios e também para poder digitar as primeiras letras de um comando e navegar apenas entre os usos anteriores deste comando em particular com as setas para cima/para baixo:

set completion-ignore-case On
"\e[B": history-search-forward
"\e[A": history-search-backward

Leia mais...

segunda-feira, 21 de maio de 2007

Túneis SSH com o gSTM

Aproveitando a deixa do BR-Linux, vou fazer um pequeno comentário a respeito de uma ferramenta que auxilia no gerenciamento de túneis SSH.

O Gnome Secure shell Tunnel Manager (o site parece estar fora do ar no momento), ou simplesmente gSTM, é uma aplicação bastante simples. Sua função, como o próprio nome já diz, é fornecer um gerenciador de túneis SSH para o Gnome.

Gnome Secure shell Tunnel Manager

Ele foi criado pelo Mark Smulders, mesmo autor do LinEAK, um utilitário para facilitar a configuração de teclados com teclas multimídia.

Os túneis SSH possuem dois propósitos básicos: permitir o acesso remoto à rede interna de um cliente e criptografar uma conexão insegura, como HTTP/FTP/SMB e a maioria dos protocolos existentes. O gSTM pode ser usado em ambos os casos e acaba sendo ainda mais útil na medida que o número de túneis que você precisa manter vai aumentando.

Se você, assim como eu, precisa se conectar a dezenas de servidores, em diferentes clientes, então você já deve ter se deparado com a situação de perder mais tempo tentando lembrar as informações de conexão ao servidor remoto do que o tempo que seria necessário para resolver o problema... ;-)

Em sistemas Debian/Ubuntu a instalação é realizada como de costume: "apt-get install gstm" ou usando o seu gerenciador de pacotes preferido...

Leia mais...

sexta-feira, 11 de maio de 2007

Melhorando a performance do ZEO

Enquanto o prêmio da Arena não chega e o Felipe/Otávio não mandam sinal de fumaça, digo, a avaliação das duas fases do Insanifying, que gerou a classificação final das quatro equipes, vou comentar a respeito de algumas mudanças quase imperceptíveis que vêm ocorrendo no ZEO nos últimos tempos. Caso a sua instalação atual do ZEO venha apresentando problemas de lentidão e/ou travamentos parciais, você vai descobrir os motivos... :-)

O servidor de aplicações Zope utiliza o ZODB (Zope Object Database) como mecanismo de persistência de objetos Python. Normalmente a área de armazenamento do ZODB pode ser usada apenas por um único processo (com uma ou mais threads, sendo quatro o número padrão). O ZEO (Zope Enterprise Objects) é a solução da Zope Corp para o compartilhamento de uma área de armazenamento única entre diversos clientes.

Quando o ZEO é utilizado, a área de armazenamento é acessada pelo processo do servidor ZEO. Então, diversos clientes podem se conectar a este servidor, de forma a compartilhar a mesma área de armazenamento. O ZEO sempre fornece uma visão consistente dos dados para todos os clientes que estiverem conectados. A comunicação entre o servidor e os clientes é feita usando uma versão personalizada do protocolo RPC, em cima do TCP.

No final do mês de março, após o lançamento das versões 2.9.7 e 2.10.3 do Zope, um bug que gerava um tempo de espera excessivamente longo após determinadas operações foi descoberto e resolvido, quase ao mesmo tempo, individualmente por duas pessoas, em locais diferentes.

A primeira solução foi apresentada pelo Jürgen Kartnaller, em 27/03/2007. Ela consistia na implementação de uma função sleep com suporte a nonosegundos, para contonar o problema da granularidade do sleep de algumas plataformas.

A segunda solução foi apresentada pouco mais de 24 horas depois, pelo já lendário Jim Fulton, também conhecido como "O" criador do Zope (qualquer semelhança com o Homer Simpson é mera coincidência!). Ele descobriu que o timeout para uma condição de chamada em espera era desnecessário, além de eliminar uma parte não assíncrona do código.

Posteriormente, parte da solução do Jim foi aplicada nos braches correspondentes às versões do ZODB que acompanham o Zope das séries 2.9.x e 2.10.x. Cabe salientar que a implementação do Jürgen se tornou desnecessária, uma vez que o timeout foi removido e com ele a chamada ao sleep.

É importante também dizer que, até o presente momento, estes aperfeiçoamentos ainda não fazem parte de nenhuma versão oficialmente lançada. Entretanto elas farão parte das versões 2.9.8 e 2.10.4, assim que elas saírem do forno.

Na tarde desta sexta-feira o Jim informou sobre mais uma possível otimização, desta vez na configuração dos parâmetros que definem os tempos mínimos (min-disconnect-poll) e máximos (max-disconnect-poll) de espera entre as tentativas de reconexão, quando os clientes se desconectam do servidor ZEO. Os valores padrão são 5 e 300 segundos e a intenção é passar a usar 1 e 6 segundos de agora em diante.

Devo confessar que nunca havia visto estes dois parâmetros antes, mas graças à mensagem do Jim e a um grep no fonte do Zope eu cheguei até o arquivo doc/ZEO/howto.txt, que explica estas e muitas outras opcões.

Os testes no ZEO passaram a rodar 25% mais rápido e o impacto em um sistema em produção pode ser ainda maior. Caso as dicas tenham sido úteis, não deixe de postar um comentário relatando a diferença de performance obtida na sua instalação.

Leia mais...

domingo, 6 de maio de 2007

Binary People

You are Binary.  You are not human and go to great lengths to prove it. You always know where you are and how you got there, but no one else does, ever.Seguindo a tendência que pudemos acompanhar nos últimos dias, onde o Érico, o Osvaldo e o Sidnei já postaram e aproveitando para dar uma força ainda maior a este meme, acabo de fazer o teste e, literalmente, deu binário... :-P

Esse era o motivo que faltava para eu encomendar a minha camiseta do ThinkGeek... :-D

O fato acabou trazendo algumas recordações... como quando aprendi a manipular estruturas de campos de bits em C e mais recentemente (ok, já fazem mais de dois anos...) quando tive que fazer algo semelhante em Python. Aliás, quando implementei isso em Python, acabei chutando um pouco o balde... foi meio overkill para o que eu estava precisando resolver, mas acabou se tornando uma solução genérica para converter números entre qualquer base numérica (com testes!), mesmo entre as bases que nem existem... ;-)

Obviamente, dois anos depois, eu posso dizer que faria aquela classe Number bem diferente, mas isso é assunto para outro post...

Leia mais...

quarta-feira, 2 de maio de 2007

Insanifying, Parte II

Terceiro e último dia da competição e do FISL. No dia anterior, os problemas exigiam que se conhecesse o mínimo da estrutura do projeto Debian. Quem não soubesse como fazer algo, poderia pedir ao Felipe ou ao Otávio e eles informariam. Poderia ainda pedir a qualquer um dos presentes no FISL ou mesmo a quem estivesse on-line. Porém, isso acabaria consumindo parte do tempo das equipes.

Eu uso o Debian nos meus servidores desde o lançamento do Potato 2.2r5 no início de 2002. Naquela época um dos meus hobbies era testar diferentes sistemas operacionais. No meu computador eu tinha cinco sistemas instalados ao mesmo tempo (Conectiva & Mandrake (agora Mandriva), NetBSD, OpenBSD, Windows e mais uma partição vazia para ficar testando outros...) quando resolvi instalar o Debian e, gradualmente, ir desinstalando os que estavam instalados... :-)

Com o lançamento do Ubuntu Warty Warthog em 2004, eu acabei deixando o Debian para ficar com o Ubuntu, que como todos devem saber, é baseada no próprio Debian. Pois bem, posso dizer que durante estes cinco anos fiquei bem familiarizado com o Debian/Ubuntu. Isso acabou ajudando a nossa equipe, pois praticamente todas as dúvidas do Guilherme e do Kalecser estavam na ponta da minha língua e acabei por me tornar uma espécie de líder para a equipe... :-)

Voltando ao terceiro dia. Novamente fizemos um círculo para receber as instruções. Dessa vez o desafio consistia em torno de um único problema, mais uma vez envolvendo o tema da fase anterior. O Debian é composto por mais de 18 mil pacotes, dos quais uma grande maioria possui suporte a internacionalização (i18n, para ser mais conciso).

A questão é que uma quantidade razoável das mensagens que precisam ser traduzidas se repetem, ou no mínimo são bastante semelhantes. Isso gera a necessidade da utilização de alguma ferramenta que implemente o conceito de Translation Memory, de forma a agilizar o processo de tradução, bem como manter a consistência quando forem utilizados termos semelhantes.

Só para dar um exemplo: o termo 'Save' está presente no menu de praticamente qualquer aplicativo gráfico. A idéia é que a tradução de todas as mensagens de todos os pacotes que utilizem esse termo fiquem iguais, no caso 'Salvar'. Isso evita a ocorrência de discrepâncias nas traduções, muito comuns em casos onde diferentes pessoas colaboram no processo de tradução. Também é importante que quando o termo for usado em outras mensagens (Save as/Save all/...) a tradução seja sugerida, agilizando o processo e reduzindo possíveis erros de consistência.

Nós recebemos um arquivo de 70MB, com uma amostra das traduções utilizadas por alguns pacotes, totalizando cerca de 300MB depois de descompactado. Cabe lembrar que essa amostra representa apenas um percentual do volume de mensagens presentes nos pacotes do Debian. Segundo o Felipe e o Otávio, atualmente nenhum dos softwares existentes (livres ou não) consegue carregar toda a base de traduções dos idiomas presentes no Debian:

>>> import re, urllib
>>> url = 'http://www.debian.org/international/l10n/po'
>>> page = urllib.urlopen(url).read()
>>> uls = re.findall('<ul>.*<ul>(.*)</ul>', page, re.DOTALL)[0]
>>> len(re.findall('<li>(.*)</li>', uls))
226

(Para os mais desavisados, o programinha acima acessa o site do Debian e salva uma cópia da página com a relação dos idiomas existentes, filtrando para ficar apenas com o segundo bloco de itens, já que o primeiro contém o menu de navegação e imprime o número de itens encontrados.)

Sim... existem 226 idiomas (ou variações de idiomas) no Debian! Impressionante!

A tarefa consistia em escrever uma especificação e realizar a implementação de um software para auxiliar no processo de tradução, permitindo que:

  • administradores possam adicionar novos pacotes no sistema;
  • tradutores possam efetuar as traduções fazendo uso do recurso de Memory Translation;
  • revisores possam acessar o sistema e sugerir alterações nas traduções já existentes.

A propósito, o nosso programa acabou sendo chamado de ATR, em função de ter que atender às necessidades das 3 classes: Administradores, Tradutores e Revisores... :-)

A primeira coisa que fizemos foi definir a estratégia. Mais uma vez sabíamos que não seria possível concluir totalmente a tarefa em tempo. Então decidimos que seria melhor fazer pelo menos um pouco de cada uma das coisas, ao invés de fazer uma das coisas bem-feita e ignorar as outras.

Precisaríamos de algo que fizesse a indexação de texto de forma rápida e sem consumir recursos demasiados do sistema. Depois de um rápido brainstorming, optamos pelo uso do Lucene, devido ao conjunto das suas características, que já contempla diferentes funções para a busca de texto. Também decidimos que a aplicação teria interface gráfica, ao invés de rodar em modo texto no console.

Como o Guilherme e o Kalecser tinham experiência na mesma linguagem de programação (Java), optamos pela seguinte divisão de tarefas:

Dorneles
especificação do sistema e desenvolvimento de qualquer coisa que levasse muito tempo em Java
Guilherme
parser dos arquivos de tradução e integração com o Lucene
Kalecser
implementação da interface gráfica

Mais uma vez o trabalho colaborativo seria fundamental. Continuamos usando o Google Docs para a especificação, mas iríamos precisar de um sistema de controle de versão para o código. Então instalei e configurei um servidor de Subversion na minha máquina. Aprendi que no mundo Java praticamente ninguém vive sem o Eclipse... e aprendi como instalar o plugin de Subversion nele também... :-)

Para termos uma noção de como era a interface gráfica do softwares já existentes, usamos o valioso serviço do Google Images. Com isso, o Kalecser e eu rascunhamos o que nós consideramos ser a melhor solução para o nosso programa.

Em seguida o Kalercer precisou extrair a relação dos idiomas disponíveis para popular um combo na tela e isso iria levar um certo tempinho em Java. Então ele pediu e eu escrevi rapidamente um programinha (4 linhas, se não me falha a memória) em Python e devolvi a saída no formato que ele havia solicitado.

Enquanto isso o Guilherme quebrava a cabeça para ver se o Java tinha algum recurso nativo para ser usado na manipulação de arquivos de catálogo de mensagens do gettext (PO e POT). Se não me engano, acabamos desenvolvendo um parser temporário e implementando nosso próprio algoritmo de busca de texto por similaridade.

Por fim, acabamos fazendo mais algumas pseudo-implementações de características que achávamos importante constar no sistema e nos preparamos para empacotar e documentar o que havíamos desenvolvido até então. O empacotamento acabou virando POG (esquecemos até a licença!), pois já tínhamos esgotado o tempo e não pudemos gerar um pacotinho Debian nos conformes... Nossa solução ficou longe do que constava na especificação, mas acredito que fizemos um bom trabalho durante o tempo determinado.

É claro que seria melhor se recebêssemos uma especificação já pronta e tivéssemos apenas que programar. O problema é que o pessoal do Debian ainda não tem uma solução para isso. Dessa forma, usaram a oportunidade de ter 12 cérebros a disposição para colher algumas idéias que poderão vir a se tornar a futura ferramenta.

Obviamente que tratava-se de um evento de programação, então entendo o fato de termos que ter programado algo para mostrar no final do dia. Caso os doze participantes tivessem trabalhado juntos, certamente o Debian teria se beneficiado mais, porém isso não seria possível nesse tipo de evento.

Encerramos a competição sem ter a menor idéia de como havia sido o nosso desempenho em comparação com as outras três equipes. Esse suspense durou mais algumas horas até o anúncio do resultado final. Mas isso é assunto para o próximo post, que só vai sair depois que o Felipe e o Otávio me enviarem o material que eles haviam prometido... ;-)

Leia mais...