Garantindo uma ordem repetível de diretório no linux


16

Dirijo uma empresa hospedada de integração contínua e executamos o código de nossos clientes no Linux. Cada vez que executamos o código, executamos em uma máquina virtual separada. Um problema frequente é que, às vezes, os testes de um cliente falham devido ao pedido de diretório de seu código verificado na VM.

Deixe-me entrar em mais detalhes. No OSX, o sistema de arquivos HFS + garante que os diretórios sejam sempre percorridos na mesma ordem. Os programadores que usam o OSX assumem que, se funcionar em sua máquina, deverá funcionar em qualquer lugar. Mas geralmente não funciona no Linux, porque os sistemas de arquivos linux não oferecem garantias de pedidos ao atravessar diretórios.

Como exemplo, considere que existem 2 arquivos, a.rb, b.rb. o a.rb define MyObjecte o b.rb usa MyObject. Se a.rb for carregado primeiro, tudo funcionará. Se o b.rb for carregado primeiro, ele tentará acessar uma variável indefinida MyObjecte falhará.

Mas pior que isso, é que nem sempre falha. Como a ordem do sistema de arquivos no Linux não é solicitada, haverá uma ordem diferente em máquinas diferentes. Isso é pior, porque às vezes os testes passam e às vezes eles falham. Este é o pior resultado possível.

Portanto, minha pergunta é: existe uma maneira de tornar a ordenação do sistema de arquivos repetível. Alguma flag para ext4, talvez, que diz que sempre irá percorrer diretórios em alguma ordem? Ou talvez um sistema de arquivos diferente que tenha essa garantia?



Além das respostas realmente verdadeiras - qual é a ordem "correta"? Apenas ordenados alfanumericamente? Ou pelo CTIME? Arbitrariamente magicamente? Como os clientes garantem esse pedido na implantação? Como essas informações mágicas sobre pedidos devem ser transferidas para você?
Michuelnik 10/07/2012

@ Michuelnik Não existe uma ordem correta, mas algo repetível significaria que sempre obtivemos o mesmo resultado, o que seria melhor do que nada. Idealmente, usaríamos a ordem HFS +, que eu acho alfabética.
Paul Biggar

@Michuelnik Esse problema afeta muito mais os testes do que a implantação. A implantação acontece principalmente no Linux, mas se algo falhar, eles irão corrigi-lo. Os testes são executados principalmente no OSX; portanto, se algo falhar, deve ser nossa culpa.
Paul Biggar

11
@PaulBiggar: Entendo o seu problema e não posso oferecer uma boa solução (a menos que você encontre uma maneira de detectar se a ordem dos arquivos é a causa do problema). Mas não concordo que "o sucesso repetível seja melhor do que falhas inconsistentes": se meu ambiente de desenvolvimento (e IC) tiver sucesso repetível, mas minha plataforma de implantação tiver a síndrome de "falha não confiável", então estou realmente em um ponto ruim. Eu sim ver o fracasso não confiável logo que possível (o ideal é no meu sistema de desenvolvimento, mas , pelo menos no meu sistema CI).
Joachim Sauer

Respostas:


16

Sei que não é a resposta que você está procurando, mas acredito que a solução correta é evitar depender da ordem dos arquivos em um diretório. Talvez seja sempre consistente em todos os sistemas de arquivos HFS +, e talvez você possa encontrar uma maneira de torná-lo consistente no ext4 ou em algum outro sistema de arquivos também, mas isso lhe custará mais problemas a longo prazo do que salvará. Alguém mais usando o seu aplicativo terá uma surpresa desagradável quando não perceberem que ele é compatível apenas com alguns tipos de sistemas de arquivos e não com outros. A ordem pode mudar se um sistema de arquivos for restaurado do backup. Você provavelmente terá problemas de compatibilidade porque a ordem consistente HFS + e a ordem consistente ext4 podem não ser as mesmas.

Basta ler todas as entradas do diretório e classificar a lista lexicograficamente antes de usá-la. Assim como lsfaz.

Você menciona arquivos a.rbe b.rb, mas se estamos falando sobre arquivos de origem da linguagem de programação, cada arquivo já não deveria ser responsável por garantir que ele importe todas as suas dependências?


O problema é que não escrevemos o código que estamos executando. Executamos o código do cliente e não temos controle sobre como o código foi escrito. Portanto, nosso problema é que realmente somos culpados pelo problema, porque ele funciona na máquina deles, mas não na nossa. Se pudéssemos forçar todos a escrever código correto, que seria, mas isso não é em nosso poder :)
Paul Biggar

10
@PaulBiggar: mas "não é executado aqui, mas não está em produção" exatamente o problema que a CI deve corrigir? Em outras palavras: "Por que meu código quebra no seu sistema?" deve ser respondido com "Porque estamos fazendo exatamente o que você está nos pedindo!" ;-)
Joachim Sauer

4
Não conheço mais ninguém, mas quando o código funciona na minha máquina e falha em um IC ou no checkout de um colega, presumo imediatamente que exista algo que depende da plataforma ou do ambiente que preciso corrigir ...
matt5784

11
Certamente desenvolver o aplicativo em uma plataforma que você não utilizará na produção é uma má idéia? Faça com que eles desenvolvam na mesma plataforma para a qual estão escrevendo.
Matthew Ife

2
Discordo. Eu acho que é uma ótima ideia. Faz com que muito mais falhas apareçam durante a mudança do desenvolvimento para os servidores de teste. E, portanto, o código é muito mais resistente antes de passar para os servidores de produção. Então, em um mundo correto ou teórico, é muito melhor. É o mesmo mundo em que você pode forçar todos a escrever o código correto, também conhecido como terra dos sonhos.
Hennes

5

A chamada POSIX no Linux readdir () não garante nenhuma ordem consistente. Se você deseja resultados ordenados, o aplicativo que está manipulando arquivos é responsável por ordenar como eles são apresentados às funções de chamada.

/programming/8977441/does-readdir-guarantee-an-order

Agora, como você disse que esse era o código do seu cliente e não pode corrigi-lo, é possível alterar as bibliotecas vinculadas usadas para fornecer uma chamada readdir () consistente. Isso exigiria algum trabalho e valeria a pena a sua própria pergunta. Para uma referência rápida a isso, consulte http://www.ibm.com/developerworks/linux/library/l-glibc/index.html .

Alterar isso pode gerar outras séries inteiras de problemas que talvez eu não consiga prever. Você é fortemente advertido, mas pode ser uma solução se seu cliente não puder ser educado adequadamente.


1

Informe seu cliente que existe uma dependência inerente ao pedido que deve ser explicitamente declarada. Ofereça-se para ajudar o cliente a expressar a dependência de forma que uma compilação funcione em todos os sistemas e faça com que o cliente adote o fluxo alterado que captura a dependência do pedido de compilação.

Se o cliente quiser poder compilar em outras máquinas, seria grosseiro da parte deles pensar que é gratuito.


Definitivamente, vamos fazer isso. No entanto, seria útil se eles realmente se tornassem nossos clientes para que pudéssemos fazer isso.
Paul Biggar

0

O Linux moderno (ext4) adiciona um índice de árvore B para listas de arquivos. Um de seus efeitos é a ordem dos arquivos padrão, depende de um hash de seus nomes.

Para desativar esse recurso, use:

tune2fs -O ^ dir_index

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.