Почему «хвост» не работает для обрезания файлов журнала? - PullRequest
10 голосов
/ 19 ноября 2009

Я пытаюсь управлять размером файла журнала, используя скрипт cron. Я в основном хочу удалять все, кроме последних 2000 строк файла журнала каждую ночь. Я пытаюсь запустить эту команду, но она, кажется, очищает весь файл вместо того, чтобы делать то, что я хочу:

tail -2000 logfile.txt> logfile.txt

Кто-нибудь знает, почему это не работает и / или как выполнить то, что я хочу? Спасибо!

Ответы [ 6 ]

14 голосов
/ 19 ноября 2009

Вы перезаписываете файл до того, как tail даже начнет его читать. Оболочка обрабатывает оператор перенаправления >, сначала удаляя файл. Затем запускается tail, у которого нет данных для чтения.

Вы можете решить эту проблему, используя временный файл:

tail -2000 logfile.txt >logfile.tmp
mv logfile.tmp logfile.txt
10 голосов
/ 17 декабря 2009

Существует проблема с принятым решением , если процесс сохраняет открытый файл журнала ; вам в основном нужно повторно использовать i-узел. Mmrobins отвечает хорошо, logrotate должен делать правильные вещи.

Чтобы использовать tail , вы можете что-то сделать (аналогично идее Pantonza & Greg), но сохранить исходный файл, обрезав оригинальный файл на месте:

tail -2000 logfile.txt >logfile.tmp
cat logfile.tmp > logfile.txt
rm logfile.tmp

Чтобы избежать временного файла, вы можете прочитать в переменную, а затем заполнить ее обратно:

bash -c 'X=$(tail -2000 logfile.txt);echo "$X">logfile.txt'

Во всех случаях существует вероятность состязания между усечением и процессом, добавляемым в файл. Не уверен, что logrotate справится с этим, ни одно из решений tail здесь не подходит.

10 голосов
/ 20 ноября 2009

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

См. Справочную страницу здесь или введите man logrotate из командной строки

Создайте новый файл logrotate в вашем каталоге /etc/logrotate.d/. Вот пример:

/var/logs/myapp/logfile.txt {
  # keep the 5 latest rotations of the log 
  rotate 5
  # rotate once the file is bigger than 2k
  size 2k
  # don't error if the file isn't there
  missingok
  # compress rotated (old) log files
  compress
  # set ownership and permissions on the new log file
  create 0640 myuser myuser
}
4 голосов
/ 19 ноября 2014

Вот еще одно решение, не связанное с файлами tmp:

echo "`tail -2000 logfile.txt`" > logfile.txt
1 голос
/ 14 марта 2016

Если вы пользователь vim, другой вариант - использовать vi вместо tail, чтобы напрямую работать с файлом:

vi "+execute \"normal! G2000kO\<esc>dgg\"" "+w" "+q" logfile.txt

Строка G2000kO\<esc>dgg - это просто ввод с клавиатуры, который вы бы использовали для этого с помощью vi (кнопка выхода должна быть экранирована). Он очень интуитивно понятен и охватывает огромный спектр вариантов использования.

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

1 голос
/ 19 ноября 2009

Грег Хьюгилл прав, logfile.txt усекается, прежде чем хвост сможет с ним работать.

попробовать:

tail -2000 logfile.txt > logfile2.txt; rm -f logfile.txt; mv logfile2.txt logfile.txt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...