Quando 'ls -s' imprime “0”

13

É claro que a maneira padrão de testar se um arquivo está vazio é com test -s FILE , mas um de nossos clientes recebeu um script contendo testes como este:

RETVAL='ls -s ./log/cr_trig.log | awk '{print $1}''
if test $RETVAL -ne 0
then
    echo "Badness: Log not empty"
    exit 25
fi

com declarações do fornecedor de que ele trabalha nos dois ambientes em que foram testadas. É desnecessário dizer que ele falhou muito nos dois locais em que testei.

Então, fiquei curioso. Quando ls -s print 0 para arquivos vazios?

Esta é a minha descoberta até agora:

  • GFS no Linux: 4
  • ext4 no Linux: 0
  • ZFS no Solaris: 1
  • UFS no Solaris: 0
  • jfs no AIX: 0
  • VxFS no HP-UX: 0
  • HFS no HP-UX: 0
  • HFS no Mac OS X: 0

Ainda não examinei sistemas de arquivos em rede.

Pergunta: Como eu posso explicar elegantemente para os outros que seus scripts estão errados ?

Na minha opinião, a versão "correta" seria:

if test ! -s ./log/cr_trig.log
then
    echo "Badness: Log not empty"
    exit 25
fi
    
por MattBianco 01.11.2011 / 09:19

3 respostas

6

Achado muito interessante. Embora eu nunca tenha usado ls -s para verificar se um arquivo está vazio ou não, eu teria assumido que ele reporta 0 para arquivos vazios também.

Para sua pergunta: Como o Mat já comentou, mostre os resultados do seu teste. Para explicar os resultados a eles, declare que ls -s informa a quantidade de blocos alocados no sistema de arquivos, não o tamanho real em bytes. Obviamente, algumas implementações do sistema de arquivos alocam blocos, mesmo que não precisem armazenar nenhum dado, em vez de armazenar apenas um ponteiro NULL no inode.

A explicação para isso pode estar relacionada ao desempenho. Criar arquivos vazios que ficarão vazios é uma exceção para o processamento normal (o uso mais comum que eu vi seria a criação de arquivos de status onde a existência de um arquivo representa um certo estado do software).

Mas normalmente um arquivo criado obterá alguns dados em breve, portanto os projetistas de um determinado FS podem ter assumido que vale a pena alocar imediatamente um bloco de dados na criação do arquivo; assim, quando os primeiros dados chegam, essa tarefa já está concluída.

O segundo motivo pode ser que um arquivo continha dados no passado que foram apagados. Em vez de liberar o último bloco de dados, pode ser útil manter esse bloco de dados para reutilização pelo mesmo arquivo.

EDITAR:

Mais uma razão veio à mente: os sistemas de arquivos nos quais você encontrou valores > 0 são ZFS , a implementação do RAID + LVM + FS e GFS , um sistema de arquivos em cluster. Ambos podem ter que armazenar metadados para manter a integridade do arquivo que não é armazenado em inodes. Pode ser que ls -s contagens em blocos de dados alocados para esses metadados.

    
por 01.11.2011 / 10:37
4

Diferentemente da maioria (se não de todos) outros sistemas de arquivos, o ZFS não pré-aloca uma matriz estática de inodes. A criação de um arquivo vazio no ZFS usará um novo bloco de dados, que é o reportado por ls -s .

Eu suspeito que o GFS tenha que armazenar dados de sincronização / bloqueio levando ao outro resultado diferente de zero.

    
por 01.11.2011 / 10:53
2

ls -s informa o número de blocos alocados para o arquivo, não incluindo o que estiver armazenado diretamente na entrada de diretório.

Na maioria dos casos, o número de blocos é o número de bytes dividido pelo tamanho do bloco em bytes, arredondado para cima.

O número de blocos pode ser menor do que o de um arquivo esparso . Por exemplo, na maioria dos sistemas de arquivos, isso criará um arquivo de 8192 bytes abrangendo 0 blocos:

$ perl -e 'truncate STDOUT, 8192' >a
$ ls -l a
-rw-r--r-- 1 gilles gilles 8192 Nov  1 21:32 a
$ ls -s a
0 a

Por outro lado, o número de blocos pode ser maior se o sistema de arquivos pré-aloca blocos para arquivos ou usa blocos para armazenar metadados. Não me surpreende que o Zfs tenha uma correspondência não óbvia entre tamanho de arquivo e número de blocos, dado o grande número de recursos que ele oferece e sua orientação para sistemas de arquivos grandes; Eu não sei os detalhes, mas o número de blocos depende não apenas do tamanho dos arquivos, mas também de seu histórico (você pode ter mais de um bloco em um arquivo vazio se for o resultado de truncar um arquivo maior).

Para explicar por que ls -s está errado: não conta o tamanho do arquivo, mas uma quantidade dependente do sistema de arquivos. É uma maneira muito indireta de determinar se um arquivo está vazio em primeiro lugar, exigindo uma ferramenta externa ( ls ) e alguma análise; em vez disso, eles devem usar test -s , que não requer análise e executa exatamente o que é solicitado. Se eles acham que ls -s é uma boa maneira de testar se um arquivo está vazio, o ônus deve estar neles para justificar que ele funciona.

    
por 01.11.2011 / 22:15