Bug no cliente FTP do Windows

2007-11-29

Dizem que uma imagem vale mais que mil palavras, então vejam esta:

Pra quem não se deu ao trabalho de entender, o enredo é o seguinte. Estou numa janela de comandos do Windows e num diretório que contém um arquivo chamado file.txt contendo oito bytes. Daí eu invoco o comando de linha “ftp” e me conecto a um servidor remoto. Verifico que não existe no servidor FTP um arquivo com o mesmo nome e me engano usando o comando “get file.txt” ao invés do “put file.txt”.

A mensagem de erro “550 file.txt: No such file or directory” é bastante clara e indica exatamente o que eu fiz de errado. Mas… ao sair do comando ftp e listar o conteúdo do diretório local sou surpreendido ao ver que o arquivo file.txt foi truncado e está com zero bytes!

Parece que quando fazemos um “get” no ftp do Windows ele abre o arquivo pra escrita antes de verificar se o arquivo existe no servidor FTP. Nesse caso, a abertura pra escrita trunca o arquivo local e o deixa com tamanho 0.

Um colega me disse que no Windows 98 e no Windows 2000 o arquivo local é removido do diretório. O exemplo acima foi executado num Windows XP, que não remove o arquivo mas o deixa vazio. Parece que eles estão melhorando… alguém pode testar no Windows Vista pra ver se já está corrigido? 🙂

Em tempo, testei na minha máquina Linux (Kubuntu 7.04) e o problema não ocorre.

Anúncios

Banda e latência

2007-11-08
Uma colega me procurou dizendo que alguns usuários estão enfrentando um sério problema de lentidão no acesso a um sistema web remoto. Cada transação neste sistema, desde o login até o logout, está demorando da ordem de 50 segundos. A reclamação já foi submetida aos administradores do sistema remoto que fizeram seus testes e disseram que os clientes locais conseguem executar as mesmas transações em dois segundos. Parece óbvio que se trata de um “problema de rede”. Mas, a sugestão imediata dos administradores, de “aumentar a banda” do nosso acesso à Internet, pode não resolver o problema.

Como este é um problema comum, resolvi registrar aqui o email que enviei pra colega, pra poder reutilizá-lo no futuro quando outro problema semelhante aparecer. (Personagens e cenários foram modificados para proteger os inocentes. 🙂

De fato, o aumento no tempo de acesso parece ser devido às diferentes situações de conectividade de rede entre o cliente e o servidor do sistema. Contudo, nem sempre um aumento de banda resolve esse tipo de problema.

Há duas características de rede que podem influenciar o tempo de resposta de uma transação: banda e latência. Banda é a quantidade de informação que a rede pode transportar por unidade de tempo e latência é o tempo que uma unidade de informação leva pra transitar pela rede de um ponto a outro.

Numa rede local trabalhamos com bandas da ordem de 100Mb/s à 1000Mb/s e latências da ordem de 1ms. Quando trabalhamos com a Internet, tratamos de bandas da ordem de 1Mb/s a 10Mb/s e latências da ordem de 100ms. Ou seja, a banda que temos pra acessar a Internet é 100 vezes menor que a banda de uma rede local e a latência é 100 vezes maior.

Essas duas características influenciam as transações de um sistema de modos diferentes. Há sistemas em que as transações são demoradas e transportam grandes volumes de dados. Imagine um repositório FTP em que as transações são o envio e a recepção de arquivos. Este tipo de sistema é bastante afetado pela banda disponível mas muito pouco afetado pela latência. Pra baixar um arquivo de 1GB da Internet leva mais de duas horas enquanto pra baixá-lo de um servidor local leva só dois minutos.

Outros sistemas são mais afetados pela latência. Imagine que ao invés de o cliente FTP fazer uma requisição para o arquivo inteiro ele precisasse fazer uma requisição para cada bloco de 1MB de dados. O mesmo arquivo de 1GB teria que ser solicitado em 1000 pedacinhos. Imagine também que cada pedaço tivesse que ser recebido antes que o próximo pudesse ser solicitado. Nesse caso, a latência passa a ser mais importante. Se numa rede local com o FTP normal o arquivo pode ser baixado em dois minutos, numa rede com a mesma banda mas com uma latência de 100ms, como ocorre na Internet, a transferência do arquivo levaria 100 segundos a mais devido ao tempo necessário para cada uma das 1000 solicitações de 100ms cada.

Tendo isso em mente é importante analisar o padrão de comunicação do sistema pra determinarmos se a lentidão quando o acesso é via Internet é determinado pela redução de banda ou pelo aumento da latência da rede. Se o padrão de comunicação for determinado por poucas requisições com grande transferência de dados então realmente o aumento na banda pode melhorar a situação. Mas se o padrão for determinado por muitas requisições pequenas, então o aumento de banda não deverá ter efeito significativo.

O ruim nisso tudo é que as soluções na camada de rede ou são caras (aumento de banda) ou inexistentes (não há como reduzir significativamente a latência na comunicação a longa distância).

Eu gostaria de simular o acesso ao sistema pra poder capturar os pacotes de rede e analisá-los pra poder verificar o padrão de comunicação. Parece-me pouco provável que uma aplicação destas tenha grandes volumes de dados trafegando entre cliente e servidor. Não conheço o sistema, mas as aplicações web mais modernas têm incorporado uma série de melhorias na interface utilizando uma tecnologia chamada AJAX. Com ela é possível que entre um clique explícito e outro do usuário o navegador dispare um grande número de requisições HTTP implícitas, o que pode tornar estas aplicações mais sensíveis a um aumento da latência da rede.

Mas isso é apenas conjectura. Se você conseguir um acesso ao sistema e um roteiro de teste eu posso tentar analisar seu padrão de comunicação pra ver se identificamos mais exatamente o problema.

Eu me lembro de ter lido um artigo muito bom sobre isso numa edição antiga da ;login:. Não consegui encontrá-lo, mas achei um outro artigo interessante do Brent Chapman sobre isso. O mais engraçado é que ele resolveu postá-lo exatamente pra poder reutilizá-lo quando tivesse que explicar o mesmo problema no futuro. 🙂


Ética dos profissionais de TI

2007-11-07
Li um artigo muito bom sobre o “estado da ética” dos profissionais de TI. Ele conclui que na maioria dos casos, estes profissionais acabam tendo que usar seu próprio juízo na hora de decidir alguma questão ética. Alguns argumentam que parte do problema é que a tecnologia tem a capacidade de distanciar o indivíduo das conseqüências de seus atos, o que nos levaria a minimizar a importância dos delitos.

O artigo sugere que pra resolver o problema seria importante que os profissionais de TI tivessem um código de ética universal, assim como os médicos e os advogados. O código serviria de padrão de conduta geral, devendo ser seguido mesmo que a empresa em que o profissional trabalhe não tenha um código específico. Além disso, deveria existir alguma organização profissional para a TI assim como a OAB para os advogados. Ela deveria ter o poder de cassar habilitações de trabalho para os profissionais que não respeitarem o código.

Já existem algumas iniciativas no sentido de criar códigos de ética ou de conduta pra TI. Em 2003 o SAGE da USENIX publicou o seu Código de Ética para Administradores de Sistemas. Ele foi divulgado no LISA’03. Eu estava lá e me lembro que foi um evento bastante comentado. A ACM é outra instituição importante que tem seu próprio código de ética.

Estes códigos são muito bons, eu acho. Serviriam muito bem como base para políticas internas e regras de conduta. Resta esperar pra ver se eles evoluirão para uma versão universal.


Deduplication

2007-10-16
Falando sobre storage, mais especificamente sobre backup, uma das tecnologias mais badaladas ultimamente é a data deduplication, ou de-dup. A idéia básica é detectar redundâncias durante o backup pra reduzir drasticamente a utilização de storage pra cópia. O stream de backup é dividido em blocos e cada bloco é identificado por uma assinatura digital. As assinaturas de todos os blocos copiados são mantidas num banco de dados. Assim, quando um novo bloco tem a mesma assinatura que outro já copiado os dados em si não precisam ser salvos novamente, apenas o banco de dados é atualizado com o índice do novo bloco apontando para o mesmo local em que o anterior foi salvo.

Confesso que até há pouco eu não havia conseguido perceber como é que os fornecedores deste tipo de solução são capazes de anunciar reduções de armazenamento da ordem de 20 ou de até 50 vezes. Não me parecia possível encontrar tanta redundância assim nos dados armazenados em disco.

Mas, acabei de ouvir um podcast no qual o Curtis Preston explica direitinho como a deduplication funciona e como é possível reduzir dezenas de vezes o consumo de storage de backup. O segredo é que o backup é um processo cíclico. Uma política de backup comum é realizar um backup full de todos os discos a cada quatro semanas. Isso significa que a cada quatro semanas todos os dados de um servidor são copiados pra fita novamente. Se usarmos um sistema de de-dup, normalmente a maioria dos dados já estaria armazenada no sistema de backup e não precisaria ser armazenada novamente, como acontece atualmente com nosso sistema de fitas.

Aliás, os sistemas de de-dup normalmente utilizam disco e não fita como storage de armazenamento exatamente porque os dados redundantes precisam ser acessados de modo aleatório e não sequencial durante um restore. A utilização de disco ao invés de fita é mais cara mas tem a vantagem de permitir restores mais rápidos e simultâneos, independentemente do número de unidades de fita disponíveis no momento.

Estou achando que vale a pena.


/net/bin SNAFU

2007-05-16

Pois é… ontem eu falei do lado bom de ser administrador de sistemas. Hoje eu preciso falar do lado ruim. Uma das piores coisas para um administrador é descobrir que fez uma besteira que afetou um monte de gente e ele não percebeu.

Enquanto eu investigava o problema de ontem eu acabei criando um script /net/bin/gawk pra tentar capturar as tentativas de usá-lo, o que acabou não sendo efetivo. Só que eu me esqueci de remover o script depois. Fiquei sabendo que vários usuários ligaram para o plantão falando que não estavam conseguindo usar o /net/gnu/bin/gawk no servidor, o que deu um bom trabalho para o pessoal que não estava sabendo do que eu estava fazendo.

Desculpe, gente! 😦

Duas lições pra qualquer administrador:

  • Sempre restaure o sistema à situação original depois de modificá-lo para fazer qualquer teste.
  • Nunca mexa num sistema de produção sem avisar seus colegas administradores antes.

Um dia eu aprendo.


A saga do /net/bin

2007-05-16

Uma das coisas mais divertidas da vida de um administrador de sistemas é resolver um problema difícil. É ainda mais legal quando o problema é antigo e você já tentou resolvê-lo várias vezes sem sucesso. Daí, quando você consegue finalmente vencê-lo, a satisfação é enorme.

Hoje tive um desses momentos memoráveis. Tanto assim que ao invés de simplesmente mandar um email para meus colegas de trabalho resolvi relatar a solução aqui e só mandar o link pra eles. Assim eles vão poder ter razão quando disserem que o Gustavo está “se achando”. 🙂

Pois bem. O mistério que nos estava deixando encucados há alguns meses eram as mensagens freqüentes que apareciam no /var/log/messages de vários servidores Linux:

May 13 16:05:02 noname automount[7655]: lookup(program): lookup for bin failed
May 13 16:05:02 noname automount[7655]: failed to mount /net/bin

Essas mensagens apareciam uma ou duas vezes por minuto, durante o dia todo, e indicavam que um ou mais processos estavam periodicamente tentando acessar o diretório /net/bin que não existe. Como o /net é a base de um mapa indireto do automounter, as falhas eram reportadas por ele via syslog.

O problema que não conseguíamos resolver era como identificar os processos que estavam acessando o diretório inexistente para podermos corrigi-los. Os logs do automounter não davam nenhuma pista útil, de modo que precisávamos de uma abordagem criativa.

O fato de os logs terem uma freqüência regular sugeria que os processos causadores pudessem estar sendo ativados via crontab. Só que essas máquinas são servidoras e têm dezenas de usuários com crontabs definidos. Os logs do /var/log/cron indicavam que grande parte dos crontabs iniciava comandos a cada minuto, de modo que não dava pra investigar um ou outro script especificamente.

Tentei pegar o culpado rastreando as chamadas de sistema do daemon crond e procurando por referências ao diretório /net/bin.

# strace -f -e trace=file -o/tmp/crond.strace -p `pidof crond`

Infelizmente, não encontrei nada, o que parecia um forte indício de que não se tratava mesmo de um processo de cron, mas eu não fiquei convencido.

Eu já tinha lido alguma coisa a respeito de ferramentas para monitorar o acesso a arquivos no Linux. Com o Google foi fácil encontrar o venerável dnotify e seu colega mais novo inotify. O dnotify permite monitorar o acesso aos arquivos de um diretório e o inotify é bem mais flexível. Só que o inotify não é suportado pela versão do kernel do servidor e eu desisti de instalar o dnotify pois provavelmente o tipo de acesso que os processos estavam fazendo não seria detectável mesmo por ele.

Uma idéia que parecia promissora era procurar por processos que tivessem o diretório /net/bin presente na sua variável de ambiente PATH. Podia ser que estes processos estivessem acessando o /net/bin como resultado do processo de busca de algum comando no PATH. Felizmente, ter a idéia foi mais difícil que implementá-la:

for e in /proc/[0-9]*/environ
do echo -n “$e: “; tr ” ’12’ <$e | grep PATH
done | grep /net/bin

Procurar nos quase 3.000 processos do servidor demorou alguns segundos mas não devolveu resultado algum. Ou o acesso não era por causa do PATH ou os processos tinham vida curta e eu não consegui acertar em nenhum deles com esse tiro.

A próxima idéia foi importante, pois me fez descobrir algumas pistas e abriu as portas para a idéia seguinte. Se os logs eram gerados porque o /net/bin não existia, talvez eu pudesse ver o resultado do acesso se eu o criasse. Exportei um diretório vazio de outra máquina e configurei o automounter para montá-lo como /net/bin na servidora. Não demorou pra eu ver que ele tinha sido montado e que as mensagens de erro pararam. Já era um avanço.

A vantagem é que agora qualquer acesso ao /net/bin deixaria um rastro de pacotes NFS na rede. Trabalho para um analisador de pacotes como o ethereal. Alguns minutos de captura e eu já tinha uma coleção razoável de pacotes NFS pra investigar. Consegui descobrir duas coisas. A primeira, promissora, foi que havia várias tentativas de acesso ao arquivo /net/bin/gawk. A segunda, ruim, foi que estes acessos eram feitos por vários usuários diferentes. Eu podia identificá-los, pois suas credenciais estavam registradas nos campos RPC dos pacotes NFS.

Daí eu pensei: se eles estão procurando o /net/bin/gawk eu vou criar um que me avise quando for invocado. Criei um script chamado gawk no diretório montado como /net/bin. O script iria registrar várias informações sobre seu chamador num arquivo e dormir por 10 minutos, de modo que eu poderia identificá-lo mais facilmente. Preparei a armadilha e fiquei esperando… Nada aconteceu. Por algum motivo os processos não estavam “chamando” o gawk falso que eu havia criado. Eu não conseguia entender porque é que algum processo procuraria o gawk se não era para chamá-lo.

Mas a idéia de forçar o travamento dos processos que estavam acessando o /net/bin era muito boa. Tinha que haver uma maneira de poder efetivá-la. A ficha caiu quando eu me lembrei da causa de um travamento recente no mesmo servidor: um servidor de NFS fora do ar. Agora que eu já tinha o /net/bin montado de um servidor NFS, bastava eu desativar o serviço remoto de NFS pra que os processos que quisessem acessar o diretório ficassem suspensos num estado de uninterruptible sleep. Tive um certo receio, pois esses travamentos devidos a problemas com servidores NFS costumam deixar os servidores num estado em que só é possível ressuscitá-los com um reboot. Ocorre que os processos que param pelo problema com o NFS podem causar a parada de outros processos que dependam deles e assim sucessivamente. Mas como eu podia restabelecer o serviço de NFS rapidamente deveria ser possível sair de qualquer enrascada.

Parei o NFS e fiquei analisando o número de processos que iam parando no estado “D”:

# ps aux | awk ‘$8 ~ /D/’

Pelo que me lembro, o número de processos assim chegou perto dos 400 em poucos minutos. Joguei o resultado num arquivo e reativei o NFS. Os processos travados voltaram a rodar e eu pude analisar o arquivo com calma. O que eu vi nele não fez muito sentido a princípio. Todos os processos parados ou eram instâncias de uma shell invocando o /net/gnu/bin/gawk ou o /net/gnu/bin/awk:

/bin/bash /net/gnu/bin/gawk …

Preciso explicar que o /net/gnu/bin é onde, historicamente, costumamos instalar as ferramentas livres do Projeto GNU nas nossas máquinas Solaris. Quando começamos a instalar servidores Linux há quase 10 anos o modelo do /net/gnu/bin não era necessário em princípio. Afinal, os sistemas Linux já vêm com todas as ferramentas do Projeto GNU instaladas nos diretórios padrão /usr/bin e /bin. Mas como o diretório /net/gnu/bin já era referenciado por uma quantidade enorme de scripts e binários antigos, pra evitar o trabalho de mexer em tudo isso alguém teve a brilhante idéia de configurar o automounter das máquinas Linux para montar o diretório local /usr/bin das máquinas como /net/gnu/bin sempre que algum processo fizesse referência explícita ao último. (Nessas horas não adianta muito ser purista. Uma solução porca e torta que “resolva o problema” é considerada boa o suficiente. Ahem.)

Tudo bem. Que o /net/gnu/bin/gawk era mesmo o /usr/bin/gawk eu sabia, mas o que é que ele tinha a ver com o inexistente /net/bin/gawk? Por que é que ao chamar o /net/gnu/bin/gawk a shell travaria se o /net/bin estivesse com o servidor NFS fora?

Isso não fazia nenhum sentido até que eu dei uma olhada de perto no dito cujo:

# ls -l /usr/bin/gawk
lrwxrwxrwx 1 root root 14 Dez 15 2005 /usr/bin/gawk -> ../../bin/gawk

Um link simbólico!?!? Pra que raios o gawk é um link simbólico? Ah… o /usr/bin/gawk está apontando para o /bin/gawk, que é onde o binário do comando está efetivamente instalado.

Cáspita! Matei a charada. Como o link simbólico é relativo, o /usr/bin/gawk aponta para o /bin/gawk mas o /net/gnu/bin/gawk acaba apontando para o /net/bin/gawk!!!

Isso explicava o fato de eu não ter encontrado nenhuma referência direta ao /net/bin com o strace: o PATH da shell tinha uma referência ao /net/gnu/bin e não ao /net/bin. O travamento ocorreu dentro do sistema operacional, na chamada ao exec, quando ele foi seguir o link simbólico.

Eu sabia que um dia eu teria uma boa razão pra dizer “bem que eu avisei” quando reclamei da gambiarra que foi o /net/gnu/bin no Linux. Agora eu tenho. 🙂

Bom, a causa do problema foi descoberta. Resta agora resolvê-lo. Idealmente, os processos que estão tentando acessar o /net/gnu/bin deveriam ser reescritos para não tentarem. Mas algo me diz que a solução vai acabar sendo criar mais uma gambiarra. Que desta vez deverá ser montar o /bin local dos servidores Linux no /net/bin.


lockd: cannot monitor

2006-07-31

Este foi um dos problemas mais chatos que eu já enfrentei… Há quase duas semanas comecei a ter problemas com o OpenOffice.org no meu Debian (testing). Creio que tudo tenha começado quando tentei instalar a versão 2.0.3 do aplicativo. Ele travava sempre que eu tentava fechar uma de suas janelas e em algumas outras situações.

Depois de alguma investigação, percebi que no /var/log/messages (e em alguns outros arquivos de log) apareciam um monte de mensagens do seguinte tipo:

lockd: cannot monitor 10.202.128.109 lockd: failed to monitor 10.202.128.109

O Google encontrou vários relatórios de erro parecido mas nenhuma solução aplicável a minha situação.

Aproveitei o ensejo e instalei o Kubuntu (dapper), coisa que eu já queria fazer há algum tempo. Mas não resolveu a questão.

No meio do caminho acabei encontrando um problema com a memória do meu micro, algumas questões relativas ao suporte ao NFS4 e acho que mais uma coisa que já esqueci.

Hoje finalmente descobri a causa do problema. Faltava instalar o pacote nfs-common. Portanto, aviso aos navegantes de Debian e distribuições derivadas… se usam NFS, não se esqueçam deste pacote.