Удалить первые N строк из активного файла журнала

26

Есть ли способ удалить первые Nстроки из журнала, который активно добавляется приложением?

Адам Матан
источник

Ответы:

10

Нет, операционные системы, такие как Linux, и их файловые системы не предусматривают удаление данных из начала файла. Другими словами, начальная точка хранения для файла является фиксированной.

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


Как отметили комментаторы, по причинам, указанным в моем предыдущем предложении, вам обычно нужно согласовывать удаление файлов журнала с программами, которые пишут журналы. Как именно это сделать, зависит от программ. Некоторые программы закрывают и снова открывают свои файлы журналов, когда вы отправляете им сигнал (например, HUP), и это можно использовать для предотвращения записи записей журнала в «удаленный» файл журнала, не прерывая работу службы.

Для управления размером файлов журнала доступно множество утилит, например, logrotate.

Некоторые программы имеют свои собственные утилиты. Например, веб-сервер Apache включает утилиту rotatelogs .

RedGrittyBrick
источник
3
Но вы не должны делать это, пока что-то все еще имеет открытый файл и все еще добавляет к нему, потому что это записало бы в теперь удаленный файл, и вы потеряете те сообщения журнала.
Tarnay Kálmán
Правда. Даже если вы использовали одно и то же имя файла.
Хеннес
Жаль, что операционные системы не позволяют вам, это было бы удобно для роторога, чтобы не перезагружать процессы после ротации: |
rogerdpack
25

Я думаю, что эта задача может быть достигнута с sed

sed -i '1,10d' myfile

удалил бы строки с 1- го по 10-й - й форме строки файла.

Я думаю, что все должны хотя бы взглянуть на этот вкладыш sed 1 .

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

sed -iсоздаст новый файл и «удалит» файл, в который выполняется запись. Большинство приложений будут продолжать записывать записи в удаленный файл журнала и продолжать заполнять место на диске. Новый усеченный файл журнала добавляться не будет. Это прекратится только после перезапуска приложения или получения других сигналов о закрытии и повторном открытии файлов журнала. В этот момент в новом файле журнала будет пробел (отсутствующие записи журнала), если между использованием sed и перезапуском приложения произошла какая-либо запись в журнале.

Безопасный способ сделать это - остановить приложение, использовать sed для усечения журнала, а затем перезапустить приложение. Этот подход может быть неприемлемым для некоторых услуг (например, веб-сервер с высокой пропускной способностью и высокими требованиями к непрерывности обслуживания)

l1zard
источник
2
Знаете ли вы, что происходит с приложениями, которые добавляются?
Адам Матан
1
Давайте предположим, что есть обычный обработчик открытого файла, который время от времени добавляет строки и сбрасывает их.
Адам Матан
1
Я знаю, как обойтись с sed, и извлечение строк в новый файл не составляет труда с sed. Проблема состоит в том, чтобы сохранить все это в одном файле.
Адам Матан
10
Нет, это не должно работать. sed -iсоздает новый файл с отредактированным контентом, а старый удаляется, поэтому вы не редактируете активный файл: $ ls -i --- 6823554 testfile --- $ sed -i 's/test/final/' testfile --- $ ls -i --- 6823560 testfile------ Пожалуйста, проверьте, как это sed -iработает. Почему у этого неправильного ответа столько голосов?
Пабук
1
Вопрос гласит «из журнала, который активно добавляется приложением». Оперативное слово «активно». Возможно, это пояснение было добавлено после того, как появился ваш ответ. Но читатели, которые тяготеют к «большинству голосов», будут введены в заблуждение. Я мог только понизить голос.
Скотт Прайв
5

Нет. Решением этой общей проблемы роста файла журнала является ротация журнала. Это включает в себя регулярное (обычно еженедельное или еженедельное) перемещение существующего файла журнала в другое имя файла и начало с пустого файла журнала. Через некоторое время старые файлы журнала удаляются.

См .: http://www-uxsup.csx.cam.ac.uk/~jw35/courses/apache/html/x1670.htm.

Тарнай Кальман
источник
2

Это ответ , а не решение. Нет никакого решения вопроса. Запрашивающий четко заявляет: «из журнала, который активно добавляется приложением». Вы можете читать дальше, чтобы понять больше, и пропустить до конца, чтобы сделать предложение, основанное на моем предположении почему этот код не соответствует рекомендациям по ведению журнала.

Чтобы было понятно: другие «ответы» здесь предлагают ложное обещание . Никакое переименование не заставит приложение использовать новый файл. Наиболее полезная информация скрыта в комментариях к этим неправильным ответам.

АКТИВНЫЕ файлы - это не какой-то контейнер, в который вы просто помещаете данные. Имя файла указывает на ОДИН индекс (начало файла), и каждый индекс имеет указатель на другой индекс (если есть больше данных). Это означает, что к постоянно записываемому файлу добавляется постоянный поток инодов, а то, что вы думаете о «файле», на самом деле представляет собой лог-последовательность инодов.

Представьте, что вы отслеживали кого-то в Картах Google, и этот человек мог телепортироваться в любую точку мира в любое время, и вы пытались соединить эти точки.

Инструмент Linux «усекать» может отбрасывать данные в конце файла, просто обходя дерево инода и (в указанном вами месте / размере) он отбрасывает все последующие указатели в стеке. Сделать обратное - сбросить данные в начале файла - было бы настолько ужасно сложным и рискованным процессом переписывания дерева инодов в режиме реального времени, что никто не напишет такие инструменты для публики, потому что они часто терпят неудачу и приводят к потеря данных. Inodes вики коротка , но объясняет некоторые из этих понятий.

** Мой совет: переверните эту проблему - ПОЧЕМУ это приложение ведет себя так? Существует множество рекомендаций по ведению журналов, но часто они связаны с тем, чем на самом деле является ваша система журналирования (системный журнал и т. Д.). По сути, ожидается, что приложение «освободит» свой дескриптор файла, поэтому logrotate (и т. Д.) Может обрабатывать дальнейшую обработку старых данных.

Всякий раз, когда я слышу «в журнале ACTIVE», я сразу же прошу этого человека рассказать мне «особую историю» этого приложения. Обычно это «выход разработчика, и мы не можем изменить код. Это на самом деле обратная сторона безопасности, имеет свой собственный набор рисков. Но я понимаю, что вам нужно решение, которое не затрагивает исходный код. Если это В этом случае требуется более конкретный вопрос.

Скотт Прайв
источник
0

Открытие в возвышенном тексте Удаление строк и сохранение файла работает каким-то образом, даже если файл добавляется, но я пришел сюда для поиска решения для решения командной строки, поэтому я бы просто оставил это рабочее, но бесполезное решение здесь !!

Ашок Кумар Саху
источник
-1

Может быть, скопировать, усечь, привязать копию обратно к усечению size = 0 и удалить копию?

Лучше, но хвост, чтобы копировать хвост, обрезать оригинал, конкат копировать хвост на оригинал.

Вы получаете строки в журнале с длиной хвоста, так что лучше, чем ограничение длины в байтах.

Исправление деталей из комментария:

Во-первых, у нас есть скрипт logger в Python3, что вы хотите

from time import sleep

idx = 0
while 1 == 1:
    idx = (idx + 1)
    lf = open('tailTrunc.log', 'a')
    lf.write("line to file " + str(idx) + '\n')
    lf.close()
    sleep(0.01)

Тогда у нас есть наш усеченный

#!/usr/bin/env bash

trap "kill 0" EXIT

rm tailTrunc.log
touch tailTrunc.log

python3 logLoop.py &
loggerPID=$!
sleep 1

kill -STOP $loggerPID
tail -10 tailTrunc.log > trimEnd.log
truncate -s 0 tailTrunc.log
kill -CONT $loggerPID
sleep 1

trimEnd.log показывает от 80 до 89

журнал показывает 90 до конца

В любом случае, там, где есть воля, есть способ.

Многие более сложные примеры консолидаторов и того, как поток записи открывается или закрывается, могут нуждаться в корректировке для каждого ядра процессора и т. Д. Просто приостановите запись и поставьте в очередь, если вы можете в своем регистраторе процесса регистрации и т. Д.

Мастер Джеймс
источник
msgstr "из журнала, который активно добавляется приложением". Проблема, которую игнорирует ваше решение, заключается в том, что файл журнала «постоянно» используется приложением - это означает, что индекс файла журнала остается в игре. Ваше решение выполняет «резервное копирование» данных файла журнала, которые могут использоваться за пределами этого вопроса.
Скотт Прайв
Спасибо за ваш комментарий и отрицательный голос? Я исправил быстрый дешевый пример как пищу для размышлений, вам нужно будет глубже подумать о вашей ситуации, но там, где есть желание, есть выход.
Мастер Джеймс
Не думаю, что это был мой отрицательный голос, но я думаю, что в комментариях к другому ответу кроется причина: если вы копируете файл журнала, то он больше не является активным файлом журнала ... независимо от того, что вы делаете. Файловый дескриптор приложения всегда будет указывать на индекс исходного файла журнала. Подумайте об этом так: у вас есть приложение, которое использует нестандартные функции ведения журнала и постоянно добавляет байты в открытый файл.
Скотт Прайв
1
Право, извините, чтобы сделать вывод. Да, inode должен оставаться прежним, поэтому в приведенном примере / доказательстве используется усечение, и опять же, это зависит от ситуации (варианты для всех, по-видимому, скрыты на простом сайте).
Мастер Джеймс