Вопрос или проблема
Я хочу уменьшить размер файла журнала до определенного минимального размера.
Я попробовал команду truncate следующим образом:
$ truncate -s 20M имя_файла_лога
Но когда я проверяю усеченный файл, он усекает последние логи и сохраняет старые.
Дальнейший анализ показал команды tail и head. Проблема в том, что команда head работает, а команда tail сохраняет содержимое в нечитаемом формате, например @@@@@@@@@@@
.
$ head -c 10M logfile > newfile
(сохраняет начало файла указанного размера)
$ tail -c 10M logfile > newfile
(сохраняет содержимое, которое невозможно прочитать)
Теперь я хочу усечь большой файл, удалив только начало файла, а не конец, и если возможно, сделать это одной командой без создания другого файла, как в head и tail. Кто-нибудь может мне помочь с этим? Спасибо!
Будучи поклонником простоты и высокой поддерживаемости, я сделал это. Я открыт для вашего мнения.
Эта команда усечяет лог-файл /tmp/myfile
, отрезая начало, а не конец файла, и не требует настройки служб и установки скриптов в несколько строк; это просто однострочная команда, которую вы можете добавить в свой crontab.
tail -c 1M /tmp/myfile > /tmp/dzqxH4ZMiSQb91uMMMgPhsgmpnc && rm /tmp/myfile && mv /tmp/dzqxH4ZMiSQb91uMMMgPhsgmpnc /tmp/myfile
Первая команда вырезает 1 МБ целевого файла во временный файл, вторая команда удаляет целевой файл, а третья переименовывает временный файл в 1 МБ как ваш целевой файл.
У него есть недостаток, что он временно выделит 1 МБ пространства в вашей файловой системе. Это может быть проблемой, если вы хотите сохранить, скажем, последний 1 ГБ вашего журнала, а ваше хранилище слишком мало или слишком медленно.
Если это ваш случай, вы можете попробовать следующее:
fallocate -c -o 0 -l 1M file
Он вырежет байты из вашего файла, начиная с позиции 0, высвобождая 1 МБ дискового пространства из вашего файла. Понимаю, что он делает это непосредственно, вместо копирования данных во временный файл. Но это требует большей сложности; вам сначала нужно вычислить текущий размер файла, чтобы знать, сколько нужно высвободить, или создать небольшой цикл, что-то вроде:
while (file larger than 100M) fallocate 1M;
в результате файл будет размером от 100 МБ до 99 МБ. Но я люблю простоту, поэтому пока предпочитаю первый вариант.
Подход:
tail -c 10M logfile > newfile
должен работать. Попробуйте ‘which tail’ и ‘where tail’, чтобы увидеть, в чём проблема.
Я использую tail -c в течение многих лет. Поскольку это становится для меня более значимым, я только что написал небольшой скрипт на tcsh, чтобы сделать это:
#!/bin/tcsh -f
set echo_style="none" ; setenv LC_ALL C #; set echo verbose
# Цель: уменьшить размер файла журнала FILE до SIZE, если он превышает
# в два раза это количество, удалив его начало.
# Использование: reducelog SIZE FILE
# Переписывает FILE.tmp
# проверка аргументов
set msg="Использование: reducelog SIZE FILE"
if ($#argv != 2) goto err
set size="$1"
set msg="Неверный уменьшенный размер SIZE"
if (`echo "$size" | grep -c '^[1-9][0-9]*$'` != 1) goto err
set file="$2"
set msg="Файл не доступен: $file"
if !(-frw "$file") goto err
# проверка, нужно ли урезать
set msg="Ошибка при нахождении размера $file"
set oldsize="`ls -l "$file" | cut -d' ' -f 5`"
if ($status) goto err
if (`echo "$oldsize" | grep -c '^[0-9][0-9]*$'` != 1) goto err
@ maxsize = $size + $size
if ("$oldsize" < "$maxsize") goto end
# быстро урезать (чтобы ничего другого не помешало)
set msg="Ошибка при уменьшении размера $file"
tail -c "$size" "$file" >! "$file.tmp"
if ($status) goto err
set msg="Ошибка при замене $file"
mv -f "$file.tmp" "$file"
if ($status) goto err
# проверить, что размер был уменьшен
set msg="Ошибка при нахождении нового размера $file"
set newsize="`ls -l "$file" | cut -s -d' ' -f 5`"
if ($status) goto err
if (`echo "$newsize" | grep -c '^[0-9][0-9]*$'` != 1) goto err
set msg="Не удалось уменьшить размер файла"
if !("$newsize" < "$oldsize") goto err
# завершено
goto end
# ошибка
err:
echo "*** $msg\!"
exit 1
# конец
end:
Причина, почему я всё еще ищу это в интернете, заключается в том, что я несколько обеспокоен (удаленной) возможностью, что какой-то процесс пишет в лог-файл, как раз когда я перемещаю его на место. Но я думаю, что просто другого способа в интернете нет.
Примечание: в приведенном выше скрипте размер SIZE указан в байтах, например, 100000 для 100 кБ.
Настройте logrotate для управления вашими файлами журналов.
Вероятно, вам нужна опция copytruncate
.
Вы также можете просто использовать tail, чтобы сохранить, например, последние 100 тыс. строк и записать вывод в другой файл
tail -n 100000 filename > filename_bak
и затем обнулить файл
$ truncate -s 0M filename
Ответ или решение
Для управления размером файлов журналов в системах IT важно придерживаться профессионального подхода, который обеспечивает сохранность последних данных и удобство использования административных инструментов. Одной из распространенных задач является уменьшение размера файла журнала без потери последних записей. Давайте подробно разберем, как эффективно решить эту задачу, учитывая предоставленный контекст.
Теория
Когда файл журнала становится слишком большим, это может привести к непредвиденным проблемам, таким как недостаток дискового пространства или усложнение анализа логов. Основная цель — удалить старые записи, сохраняя актуальные данные. Мы можем воспользоваться утилитами, доступными в UNIX-подобных системах, такими как truncate
, tail
, head
, а также инструментами администрирования журналов, например, logrotate
.
Проблемы при использовании стандартных команд
-
truncate: Команда
truncate -s 20M лог_файл
удаляет часть файла, начиная с его конца, оставляя начало файла неизменным. Это не подходит, если вам нужно сохранить последние записи. -
tail: Хотя команда
tail -c 10M лог_файл
должна оставить последние 10 МБ файла, вы столкнулись с проблемой, когда вывод не читаемый. Это может быть связано с кодировкой или особенностями содержимого. -
head: Команда
head
успешно извлекает начало файла, но это противоположно вашей цели.
Пример
На практике типичное решение предложено в виде использования временных файлов для сохранения последнего блока данных:
tail -c 1M /tmp/myfile > /tmp/tempfile && mv /tmp/tempfile /tmp/myfile
Этот метод позволяет извлекать последний 1 МБ из файла и замещать оригинальный файл обновленной версией. Однако это имеет недостаток в виде временного использования дискового пространства. Более сложные методы, такие как использование fallocate
, предоставляют возможность уменьшения размера файла без создания временных файлов, но требуют более детальной настройки.
Применение
Для автоматизации процесса управления размером журналов можно использовать инструмент logrotate
. Этот утилит позволяет:
- Конфигурировать политики ротации файлов, включая временные интервалы и условия.
- Использовать опцию
copytruncate
, чтобы копировать содержимое файла в новый файл и обрезать исходный, не прерывая работу служб.
Пример конфигурации logrotate
:
/tmp/myfile {
size 20M
copytruncate
create 644 root root
rotate 7
compress
}
Заключение
Эффективное управление файлами журналов требует понимания особенностей имеющихся команд и инструментов. Важно выбирать подходы, которые не только решают текущую задачу, но и минимизируют риск сбоев в будущем. Использование logrotate
с параметром copytruncate
— наилучшее решение для бизнес-среды, обеспечивающее непрерывность работы систем и минимизацию интервенции администраторов.
Настройка может быть дополнительно усложнена в зависимости от размеров файлов, частоты логирования и доступного дискового пространства, поэтому рекомендуется регулярно пересматривать конфигурации на предмет их актуальности с развитием вашей IT-инфраструктуры.
Таким образом, тщательное планирование и тестирование предложенных методов обеспечит надежную и эффективную работу с логами в условиях корпоративных IT-систем.