tee -a не воссоздает файл

tee -a не воссоздает файл

Я запускаю следующую команду на Raspberry Pi 3 последней версии Debian:

cat /dev/ttyUSB0 | tee -a /media/pi/KINGSTON/klima.out | grep -F $ | tee -a /media/pi/KINGSTON/log

Команда работает отлично и делает то, что должна; однако, когда я удаляю (вручную или через CRON) файл klima.out, он не создается заново. Команда продолжает выполняться, файл журнала продолжает добавляться, но файл klima.outне возвращается. (также нет буферизации). Я хочу удалять его раз в неделю, чтобы он не перерастал все границы. Есть предложения?

решение1

Я предполагаю, что ваш конвейер работает уже долгое время и вы пытаетесь удалить файл журнала, пока он работает.

Когда вы удаляете файл, teeпроцесс все еще держит его открытым для записи, что означает, что дисковое пространство не возвращается системе. Это не произойдет, пока все открытые файловые дескрипторы, ссылающиеся на файл, не будут закрыты.

Запись в файл, который был удален, совершенно допустима, если дескриптор файла был выделен до удаления.

Вам придется перезапустить конвейер, чтобы файл был создан заново и чтобы освободить место, занимаемое старым (теперь безымянным) файлом журнала.

Чтобы избежать необходимости перезапускать конвейер, вы можете выбратьусекатьфайл, т.е. обрезать его размер до нуля, не удаляя его. Это позволит teeпродолжить добавление в файл без необходимости его повторного открытия.

Усечение файла может быть выполненокак jlliagre показал в своем ответе, или с помощью truncate(нестандартной утилиты, которая является частью GNU coreutils):

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

Видетьруководство дляtruncateдля получения дополнительной информации об этой утилите.

решение2

Если вы хотите восстановить блоки файла, вам необходимо очистить файл, а не отключать его:

Этот портативный способ должен работать с большинством оболочек:

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

Удаление ссылки на файл (т.е. rm) удаляет запись каталога, но не влияет на содержимое файла (inode), пока файл остается открытым для чтения или записи.

решение3

Вы не понимаете, как система обрабатывает файлы.

Вы удаляете запись файла, но файл все еще существует, пока программа хранит его. Поэтому tee никогда не уведомляется о том, что запись была удалена, и он все еще пишет в файл!

Уникальный файл может иметь множество записей благодаря жестким ссылкам (создаваемым командой ln).

Вы можете написать собственную версию tee, которая будет закрывать и открывать файл на каждой строке, записываемой в файл, но это будет очень неэффективно, поскольку будет генерировать слишком много системных вызовов.

Вот функция оболочки, которая разделит входные данные на несколько файлов:

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
}

(Вы можете использовать «head» вместо «dd», если вы указываете количество строк вместо размера.)

В bash вы можете использовать «подстановку процессов» следующим образом:

prog1 | tee >( splitInput somefilename ) | prog2

Связанный контент