Quando `ls -s` imprime" 0 "

13

Obviamente, 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 alegações do fornecedor de que ele trabalha nos dois ambientes em que o testaram. Desnecessário dizer que ele falhou muito nos dois locais em que o testei.

Então, fiquei curioso. Quando é que ls -simprime 0para arquivos vazios?

Estas são as minhas descobertas 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 os sistemas de arquivos em rede.

Pergunta: Como posso explicar elegantemente aos 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
MattBianco
fonte
5
Apenas mostre a eles seus testes. Você tem dados concretos que provam que o teste deles não é portátil, do que mais você precisa?
Mat
Uma das perguntas mais interessantes que já vi até agora neste servidor. Pena que só se pode gastar um ponto.
Ktf
@ktf Você sempre pode conceder uma recompensa.
5111 Joe

Respostas:

6

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

Para sua pergunta: como Mat já comentou, mostre a eles seus resultados de teste. Para explicar os resultados, indique que ls -srelata a quantidade de blocos alocados no sistema de arquivos, não o tamanho real em bytes. Obviamente, algumas implementações de sistema de arquivos alocam blocos, mesmo que não precisem armazenar dados, em vez de armazenar apenas um ponteiro NULL no inode.

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

Porém, normalmente, um arquivo criado receberá alguns dados em breve; portanto, os designers de um determinado FS podem ter assumido que vale a pena alocar imediatamente um bloco de dados na criação do arquivo; portanto, quando os primeiros dados chegarem, essa tarefa já estará concluída.

A segunda razão pode ser que um arquivo continha dados no passado que foram apagados. Em vez de liberar o último bloco de dados, pode valer a pena manter esse bloco de dados para reutilização no mesmo arquivo.

EDITAR:

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

ktf
fonte
4

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

Suspeito que o GFS precise armazenar dados de sincronização / bloqueio levando a outro resultado diferente de zero.

jlliagre
fonte
2

ls -s relata o número de blocos alocados para o arquivo, sem incluir o que estiver armazenado diretamente na entrada do 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 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é-alocar blocos para arquivos ou usar blocos para armazenar metadados. Não estou surpreso que o Zfs tenha uma correspondência não óbvia entre o tamanho do arquivo e o número de blocos, dado o grande número de recursos que ele oferece e sua orientação para grandes sistemas de arquivos; Não conheço 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 -sestá errado: ele 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 algumas análises; em vez disso, eles devem usar test -s, o 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 funciona.

Gilles 'SO- parar de ser mau'
fonte