Why would you cat /dev/null onto anything?
Você fará isso para truncar o conteúdo de um arquivo enquanto mantém o inode intacto. Todos os programas que têm esse arquivo aberto para leitura ou gravação não seriam afetados fora do fato de que o tamanho do arquivo seria zerado.
Uma alternativa falsa 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 gravado por qualquer processo que tenha o arquivo excluído aberto no momento da exclusão. A razão pela qual está sob sistemas de arquivos Unix, quando você exclui um arquivo, você apenas desvincula seu nome (caminho) de seu conteúdo (inode). O inode é mantido vivo enquanto houver processos que o abrem para leitura ou escrita.
Isso leva a vários efeitos negativos: os logs escritos após a exclusão do arquivo são perdidos, pois não há uma maneira direta / portátil de abrir um arquivo excluído. Enquanto um processo estiver gravando no arquivo excluído, seu conteúdo ainda estará usando espaço no sistema de arquivos. Isso significa que, se você remover / criar o arquivo porque ele estava preenchendo o disco, o disco ficará cheio. Uma maneira de corrigir este último problema é reiniciar os processos do registrador, mas você pode não querer fazer isso para serviços críticos e logs intermediários seriam definitivamente perdidos. Há também efeitos colaterais devido ao fato de que o arquivo que você cria pode não ter as mesmas permissões, proprietário e grupo do que o original. Isso, por exemplo, pode impedir que um analisador de logs leia o arquivo recém-criado ou, pior, impedir que o processo de registro grave seus próprios registros.
O primeiro método, cat /dev/null > file
atinge 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 que é vazio por design, falha em ler qualquer coisa e finalmente sai. Usar esse comando é um desperdício de pressionamentos de teclas, bytes, chamadas do sistema e ciclos de CPU, e pode ser substituído sem qualquer alteração funcional pelo comando sem operação mais rápido :
ou mesmo, com a maioria dos shells, sem comando algum .
Deixe-me tentar uma metáfora para explicar o quanto cat /dev/null
é inútil. Digamos que seu objetivo seja esvaziar um copo.
-
Primeiro remova qualquer líquido dela. Isso é suficiente e é precisamente o que ( > file
) faz, já que os redirecionamentos são sempre processados primeiro.
-
Depois, você escolhe uma garrafa vazia ( /dev/null
) e despeja-a no copo vazio ( cat
). Este é o passo inútil ...
Se você ler seu documento vinculado até o final, talvez perceba os comentários neste linha da versão aprimorada do script:
cat /dev/null > wtmp # ': > wtmp' and '> wtmp' have the same effect.
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 ( csh
e sh
families):
cd /var/log
: > messages
: > wtmp
echo "Log files cleaned up."
e isso funcionará com todos os shells usando a sintaxe Bourne, como ash
, bash
, ksh
, zsh
e os gostos:
cd /var/log
> messages
> wtmp
echo "Log files cleaned up."
No entanto, com antigos shells pré-POSIX Bourne, qualquer um desses comandos, incluindo cat /dev/null
, não truncará um arquivo se for escrito posteriormente por um shell script ainda em execução anexado a ele. Em vez de um arquivo de zero bytes, isso seria um arquivo esparso com seu tamanho inalterado. O mesmo aconteceria se o arquivo fosse escrito por um processo buscando a posição que ele acha que é a atual antes de escrever.
Tenha também em atenção que algumas soluções alternativas sugeridas para truncar um ficheiro apresentam 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
que armazenam registros de largura fixa.
echo > file
echo "" > file
-
O próximo baseado em uma opção BSD sh
não é portátil, POSIX não especifica nenhuma opção permitida para echo, então você pode acabar com um arquivo contendo uma linha com " -n
":
echo -n > file
-
Esse não é portátil usando uma seqüência de escape do System V sh
. Algumas shells criarão um arquivo contendo uma linha com " \c
":
echo "\c" > file
-
Esse usa um comando projetado para fazer o trabalho. O problema é usar truncate
não é portável porque este comando, não sendo especificado pelo POSIX, pode estar faltando em um sistema Unix / Linux.
truncate -s 0
Por fim, aqui estão algumas alternativas que são portáteis e que farão o trabalho corretamente:
-
Explicitamente imprimindo uma string vazia para o arquivo:
printf "" > file
-
Usando o comando true
, que é estritamente equivalente ao não-operado, um :
, embora seja mais legível:
true > file