Por que você colocaria / dev / null em algo?
Você fará isso para truncar o conteúdo de um arquivo enquanto mantém o inode intacto. Todos os programas que possuem esse arquivo aberto para leitura ou gravação não seriam afetados fora do fato de que o tamanho do arquivo seria redefinido para zero.
Uma alternativa falsa frequentemente encontrada é remover o arquivo e criá-lo novamente:
rm file
touch file
ou similar:
mv file file.old
gzip file.old
touch file
O problema é que esses métodos não impedem que o arquivo antigo seja mantido gravado por quaisquer processos que tenham o arquivo excluído aberto no momento da exclusão. A razão pela qual está em sistemas de arquivos Unix, quando você exclui um arquivo, você desvincula apenas o nome (caminho) do conteúdo (inode). O inode é mantido ativo enquanto houver processos abertos para leitura ou gravação.
Isso leva a vários efeitos negativos: os logs gravados após a exclusão do arquivo são perdidos, pois não há uma maneira simples / portátil de abrir um arquivo excluído. Enquanto um processo está gravando no arquivo excluído, seu conteúdo ainda está usando espaço no sistema de arquivos. Isso significa que, se você remover / criar o arquivo porque estava preenchendo seu disco, ele permanecerá preenchido. Uma maneira de corrigir esse último problema é reiniciar os processos do criador de logs, mas talvez você não queira fazer isso para serviços críticos e os logs intermediários seriam definitivamente perdidos. Também existem efeitos colaterais, porque o arquivo que você cria pode não ter as mesmas permissões, proprietário e grupo que o original. Isso, por exemplo, pode impedir que um analisador de logs leia o arquivo recém-criado ou, pior ainda, evite que o processo de log grave seus próprios logs.
O primeiro método, cat /dev/null > file
atingir o objetivo corretamente , no entanto, apesar de uma lenda urbana tenaz, sua cat /dev/null
parte não faz absolutamente nada útil. Ele abre um pseudo arquivo vazio por design, não consegue ler nada dele e, finalmente, sai. O uso desse comando é um desperdício de pressionamentos de tecla, bytes, chamadas de sistema e ciclos de CPU e pode ser substituído sem nenhuma alteração funcional pelo comando no-op, sem dúvida, mais rápido :
ou mesmo, com a maioria dos shells, por nenhum comando.
Deixe-me tentar uma metáfora para explicar como cat /dev/null
é inútil . Digamos que seu objetivo é esvaziar um copo.
Você primeiro remove qualquer líquido dele. Isso é suficiente e é precisamente o que ( > file
) faz, pois os redirecionamentos são sempre processados primeiro.
Depois, você escolhe uma garrafa vazia ( /dev/null
) e despeja no copo vazio ( cat
). Este é o passo inútil ...
Se você ler o documento vinculado até o final, poderá observar os comentários nesta linha na versão aprimorada do script:
cat / dev / null> wtmp # ':> wtmp' e '> wtmp' têm o mesmo efeito.
Eles realmente têm; muito ruim cat /dev/null
foi mantido no código.
Isso significa que o código a seguir funcionará com todos os shells comuns (ambos csh
e sh
famílias):
cd /var/log
: > messages
: > wtmp
echo "Log files cleaned up."
e isso vai funcionar com todas as conchas usando a sintaxe Bourne, como ash
, bash
, ksh
, zsh
e os gostos:
cd /var/log
> messages
> wtmp
echo "Log files cleaned up."
Observe, no entanto, que com shells antigos Bourne pré-POSIX, qualquer um desses comandos, inclusive cat /dev/null
, não truncará um arquivo se ele for gravado posteriormente por um script de shell ainda em execução anexado a ele. Em vez de um arquivo de zero byte, seria um arquivo esparso com seu tamanho inalterado. O mesmo aconteceria se o arquivo fosse gravado por um processo buscando a posição que ele pensa ser a atual antes de ser gravada.
Observe também que algumas soluções alternativas frequentemente sugeridas para truncar um arquivo têm falhas.
Ambos os seguintes simplesmente não fazem o trabalho. O arquivo resultante não está vazio, mas contém uma linha vazia. Isso quebraria arquivos de log como wtmp
esse que armazenam registros de largura fixa.
echo > file
echo "" > file
A próxima baseada em uma sh
opção BSD não é portátil, o POSIX não especifica nenhuma opção permitida para eco, portanto, você pode acabar com um arquivo contendo uma linha com " -n
":
echo -n > file
Esse também não é portátil, usando uma sh
sequência de escape do System V. Alguns shells criarão um arquivo contendo uma linha com " \c
":
echo "\c" > file
Esse usa um comando projetado para fazer o trabalho. O problema usado truncate
não é portátil, pois esse comando, não sendo especificado pelo POSIX, pode estar ausente em um sistema Unix / Linux.
truncate -s 0
Finalmente, aqui estão algumas alternativas que são portáteis e farão o trabalho corretamente:
Imprimindo explicitamente uma sequência vazia no arquivo:
printf "" > file
Usando o true
comando que é estritamente equivalente ao no-op, :
embora mais legível:
true > file