Estou executando o seguinte comando em uma versão mais recente do Raspberry Pi 3 Debian:
cat /dev/ttyUSB0 | tee -a /media/pi/KINGSTON/klima.out | grep -F $ | tee -a /media/pi/KINGSTON/log
O comando funciona bem e faz o que deveria; entretanto, quando eu excluo (manualmente ou por CRON) o klima.out
arquivo, ele não é recriado. O comando continua em execução, o arquivo de log continua sendo anexado, mas o klima.out
arquivo não volta. (também sem buffer). Quero excluí-lo uma vez por semana para não deixá-lo crescer além de todos os limites. Alguma sugestão?
Responder1
Presumo que seu pipeline esteja em execução há muito tempo e que você esteja tentando remover o arquivo de log enquanto ele está em execução.
Ao excluir o arquivo, o tee
processo ainda o mantém aberto para gravação, o que significa que o espaço em disco não é devolvido ao sistema. Isso não acontecerá até que todos os descritores de arquivo abertos que fazem referência ao arquivo sejam fechados.
É perfeitamente normal gravar em um arquivo que foi excluído, desde que o descritor de arquivo tenha sido alocado antes da exclusão.
Você terá que reiniciar o pipeline para que o arquivo seja recriado e para permitir que o espaço ocupado pelo arquivo de log antigo (agora sem nome) seja recuperado.
Para evitar ter que reiniciar o pipeline, você pode optar portruncaro arquivo, ou seja, reduza seu tamanho para zero sem removê-lo. Isso permitiria tee
continuar anexando ao arquivo sem precisar reabri-lo.
Truncar um arquivo pode ser feitocomo jlliagre mostrou em sua resposta, ou usando truncate
(um utilitário não padrão que faz parte do GNU coreutils):
truncate -s 0 /media/pi/KINGSTON/klima.out
Vero manual paratruncate
para obter mais informações sobre esse utilitário.
Responder2
Se quiser recuperar os blocos de arquivo, você precisa deixar o arquivo em branco, e não desvinculá-lo:
Esta forma portátil deve funcionar com a maioria dos shells:
: > /media/pi/KINGSTON/klima.out
Desvincular o arquivo (ou seja rm
, ) remove a entrada do diretório, mas não afeta o conteúdo do arquivo (inode), desde que o arquivo seja mantido aberto por leitores ou gravadores.
Responder3
Você não entende como o sistema está lidando com arquivos.
Você exclui a entrada do arquivo, mas o arquivo ainda existe enquanto o programa mantiver um controle sobre ele. Portanto, tee nunca é notificado de que a entrada foi excluída e ainda grava no arquivo!
Um arquivo exclusivo pode ter muitas entradas graças aos links físicos (criados pelo comando ln).
Você poderia escrever sua própria versão do tee, que fecha e abre o arquivo em cada linha que ele grava no arquivo, mas teria um desempenho muito inferior, pois geraria muitas chamadas de sistema.
Aqui está uma função shell que dividirá sua entrada em vários arquivos:
splitSizeInKio=100
splitInput(){
local PS4='+splitInput+ '
set -x
local i=0
local fname="$1"
local ii
while true
do if [ $i -lt 10 ]
then ii=0$i
else ii=$i
fi
local outfile="$fname".$ii
dd of="$outfile" bs=1024 count=$splitSizeInKio
i=$((i+1))
done
}
(Você poderia usar "head" em vez de "dd" se derramasse várias linhas em vez de um tamanho.)
Com o bash, você pode usar "substituição de processo" assim:
prog1 | tee >( splitInput somefilename ) | prog2