tee -a does not recreate file

I'm assuming that the pipeline of yours is running for a long time and that you are trying to remove the log file while it's running.

When you delete the file, the tee process still has it open for writing, which means that the disk space is not handed back to the system. That won't happen until all open file descriptors that references the file are closed.

It's perfectly OK to write to a file that's been deleted, as long as the file descriptor was allocated before the deletion.

You will have to restart the pipeline for the file to be recreated, and to allow the space taken by the old (now nameless) log file to be reclaimed.

To avoid having to restart the pipeline, you may choose to truncate the file, i.e. trim its size down to zero without removing it. This would allow tee to continue appending to the file without having to re-open it.

Truncating a file may be done like jlliagre showed in his answer, or by using truncate (a non-standard utility which is part of GNU coreutils):

truncate -s 0 /media/pi/KINGSTON/klima.out

See the manual for truncate for further info about that utility.


If you want to recover the file blocks, you need to blank the file, not unlink it:

This portable way should work with most shells :

: > /media/pi/KINGSTON/klima.out

Unlinking the file (i.e. rm) is removing the directory entry but doesn't affect the file contents (inode) as long as the file is kept open by readers or writers.


You don't understand how the system is handling files.

You delete the file entry, but the file still exists as long as the program keeps an handle on it. So tee is never notified the entry was deleted and it still writes to the file !

A unique file can have many entries thanks to the hard links (created by the ln command).

You could write your own version of tee which close and open the file on every line it writes to the file, but it would be very under-performing as it would generate so many system calls.

Here is a shell-function which will split its input to several files :

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
}

(You could use "head" instead of "dd" if you spilt on a number of lines instead of a size.)

With bash, you can use "process substitution" like this :

prog1 | tee >( splitInput somefilename ) | prog2

Tags:

Tee

Rm