Я пытаюсь сохранить последние 50 строк в моем файле, где я сохраняю температуру каждую минуту. Я использовал эту команду:
tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test
Но результат - пустой тестовый файл. Я думал, он перечислит последние 50 строк тестового файла и вставит его в тестовый файл. Когда я использую эту команду:
tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test2
это работает нормально. В файле test2 50 строк.
Кто-нибудь может объяснить мне, где проблема?
command-line
logs
tail
dorinand
источник
источник
logging
модульОтветы:
Проблема в том, что ваша оболочка настраивает конвейер команд перед запуском команд. Дело не в «вводе и выводе», а в том, что содержимое файла уже удалено до того, как tail запустится. Это выглядит примерно так:
>
выходной файл для записи, обрезая егоtail
.tail
бегает, открывает/home/pi/Documents/test
и ничего не находит тамСуществуют различные решения, но главное - понять проблему, что на самом деле идет не так и почему.
Это произведет то, что вы ищете,
Пояснение:
$()
называется подстановка команды, которая выполняетtail -n 50 /home/pi/Documents/test
> /home/pi/Documents/test
перенаправляет выводecho "$(tail -n 50 /home/pi/Documents/test)"
в тот же файл.источник
bash: xrealloc: cannot allocate 18446744071562067968 bytes
Другое решение для перенаправления файла, сначала очищающее файл, заключается в использовании
sponge
изmoreutils
пакета следующим образом:источник
Это связано с тем, что bash обрабатывает перенаправление
>
первым, удаляя содержимое файла. Затем он выполняет команду. Если бы вы использовали>>
, последние 50 строк были бы добавлены в конец того, что в настоящее время находится в файле. В этом случае вы бы повторили 50 одинаковых строк.Команда работает, как и ожидалось, при перенаправлении в другой файл. Вот один из способов записать последние 50 строк файла в файл с таким же именем:
Это сначала записывает последние 50 строк во временный файл, который затем перемещается с помощью
mv
замены исходного файла.Как отмечено в комментариях, это не будет работать, если файл все еще открыт. Перемещение файла также создает новый индекс и может изменить владельца и разрешения. Лучший способ сделать это, используя временный файл:
Временный файл также может быть удален, хотя каждый раз, когда это происходит, его содержимое будет перезаписываться.
источник
tail -50 /home/pi/Documents/test >/tmp/foo && cat /tmp/foo >/home/pi/Documents/test
tail ... > temp ; cat temp > orig ; rm -f temp
работает.Поскольку вы видели основную проблему с перенаправлением оболочки, вот альтернативный способ сокращения файла до последних 50 строк:
Тяжелую работу выполняет (GNU) sed с
-i
функцией «редактирования на месте», которая работает под прикрытием, создавая выходные данные во временном файле. Остальные строки настраивают математику для работы sed, а именно:wc
), затем вычесть 50; назначьте этоn
.n
положительно, выполните команду sed, чтобы удалить строки с 1 по n.источник
printf
используется для передачи команд (по одной на строку) вed
. Этиed
команды являются:1,$-50d
- удалить все, кроме последних 50 строкw
- записать измененный файл обратно на дискПеренаправления не применяются, поэтому оболочка не может перезаписать выходной файл до того, как он будет прочитан.
Кроме того, в отличие от большинства форм редактирования «на месте» (которые обычно имитируют редактирование «на месте» путем создания временного файла с последующим переименованием его поверх оригинала),
ed
фактически редактирует исходный файл - поэтому он сохраняет тот же индекс ( а владелец, группа и права доступа - tempfile + mv всегда изменяет inode и может изменять другие в зависимости от обстоятельств).источник
С другой стороны, вы можете
logrotate(8)
регулярно выполнять резервное копирование файлов журналов, чтобы постепенно называть файлы, а затем удалять старые.Вот как управляются основные системные журналы, чтобы они не росли слишком долго.
источник