Добавление метки метки времени вместе с строками файла журнала

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

Может кто-нибудь, пожалуйста, помогите мне с идеей создания этого скрипта?

4 Solutions collect form web for “Добавление метки метки времени вместе с строками файла журнала”

Общий путь

$ cat input.log | sed -e "s/^/$(date -R) /" >> output.log 

Как это работает:

  1. cat читает файл с именем input.log и просто печатает его в своем стандартном потоке вывода.

    Обычно стандартный вывод подключается к терминалу, но этот маленький скрипт содержит | поэтому shell перенаправляет стандартный вывод cat на стандартный ввод sed .

  2. sed считывает данные (как производит cat ), обрабатывает его (согласно сценарию с опцией -e ), а затем выводит его на стандартный вывод. Сценарий "s/^/$(date -R) /" означает замену каждого начала строки на текст, сгенерированный командой date -R (общая конструкция для команды replace: s/pattern/replace/ ).

  3. Затем согласно >> bash перенаправляет вывод sed в файл с именем output.log ( > означает замену содержимого файла и >> означает добавление в конец).

Проблема заключается в том, что $(date -R) оценивается один раз при запуске скрипта, чтобы он вставлял текущую временную метку в начало каждой строки. Текущая временная метка может быть далека от момента, когда было создано сообщение. Чтобы избежать этого, вы должны обрабатывать сообщения, поскольку они записываются в файл, а не с заданием cron.

ФИФО

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

Выберите пример:

 $ mkfifo foo.log.fifo $ while true; do cat foo.log.fifo | sed -e "s/^/$(date -R) /" >> foo.log; done; # have to open a second terminal at this point $ echo "foo" > foo.log.fifo $ echo "bar" > foo.log.fifo $ echo "baz" > foo.log.fifo $ cat foo.log Tue, 20 Nov 2012 15:32:56 +0400 foo Tue, 20 Nov 2012 15:33:27 +0400 bar Tue, 20 Nov 2012 15:33:30 +0400 baz 

Как это работает:

  1. mkfifo создает именованный канал

  2. while true; do sed ... ; done while true; do sed ... ; done запускает бесконечный цикл, и на каждой итерации он запускает sed с перенаправлением foo.log.fifo на его стандартный ввод; sed блокирует ожидание входных данных, а затем обрабатывает полученное сообщение и печатает его на стандартный вывод, перенаправленный в foo.log .

    На этом этапе вам нужно открыть новое окно терминала, потому что цикл занимает текущий терминал.

  3. echo ... > foo.log.fifo выводит сообщение на стандартный вывод, перенаправленный на файл fifo, и sed получает его, обрабатывает и записывает в обычный файл.

Важное замечание – fifo так же, как любая другая труба не имеет смысла, если одна из ее сторон не связана с каким-либо процессом. Если вы попытаетесь записать в трубу, текущий процесс будет блокироваться, пока кто-то не будет читать данные с другой стороны трубы. Если вы хотите читать из канала, процесс блокируется, пока кто-то не напишет данные в трубу. sed петля в приведенном выше примере ничего не делает (спит), пока вы не выполните echo .

Для вашей конкретной ситуации вы просто настраиваете приложение для записи сообщений журнала в файл fifo. Если вы не можете его настроить – просто удалите исходный файл журнала и создайте файл fifo. Но обратите внимание, что если цикл sed будет умирать по какой-то причине – ваша программа будет заблокирована при попытке write файл, пока кто-то не read из fifo.

Преимущество – это текущая временная метка, которая оценивается и прикрепляется к сообщению, когда программа записывает его в файл.

Асинхронная обработка с tailf

Чтобы сделать запись в журнал и обработка более независимой, вы можете использовать два обычных файла с tailf . Приложение будет записывать сообщение в необработанный файл, а другой процесс – читать новые строки (следовать за записью асинхронно) и обрабатывать данные с записью во второй файл.

Приведем пример:

 # will occupy current shell $ tailf -n0 bar.raw.log | while read line; do echo "$(date -R) $line" >> bar.log; done; $ echo "foo" >> bar.raw.log $ echo "bar" >> bar.raw.log $ echo "baz" >> bar.raw.log $ cat bar.log Wed, 21 Nov 2012 16:15:33 +0400 foo Wed, 21 Nov 2012 16:15:36 +0400 bar Wed, 21 Nov 2012 16:15:39 +0400 baz 

Как это работает:

  1. Запустите процесс tailf который будет следовать за bar.raw.log в bar.raw.log и распечатать их до стандартного вывода, перенаправленного на бесконечный, в while read ... echo loop. Этот цикл выполняет два действия: считывает данные со стандартного ввода в буферную переменную, называемую line а затем записывает созданную bar.log метку со следующими буферизованными данными в bar.log .

  2. Напишите некоторые сообщения в bar.raw.log . Вы должны сделать это в отдельном окне терминала, потому что первый будет занят tailf который будет следовать за tailf и выполнять свою работу. Довольно просто.

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

Вы можете использовать скрипт ts perl из moreutils :

 $ echo test | ts %F-%H:%M:%.S 2012-11-20-13:34:10.731562 test 

Изменен ответ Дмитрия Васильянова.

В сценарии bash вы можете перенаправлять и переносить вывод с меткой времени по очереди на лету.

Когда использовать:

  • Для заданий сценария bash вставьте строку перед основным скриптом
  • Для заданий без сценария создайте сценарий для вызова программы.
  • Для управления сервисами по системе лучше использовать tailf для файла журнала, как сказал Дмитрий Васильянов.

Пример с именем foo.sh :

 #!/bin/bash exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line" >> foo.log; done;) echo "foo" sleep 1 echo "bar" >&2 sleep 1 echo "foobar" 

И результат:

 $ bash foo.sh $ cat foo.log May 12 20:04:11 foo May 12 20:04:12 bar May 12 20:04:13 foobar 

Как это работает

  1. exec &> Перенаправить stdout и stderr в одно и то же место
  2. >( ... ) выхода асинхронной внутренней команды
  3. Остальная часть работает по мере расширения Дмитрия Васильянова.

Например:

  • метка времени и запись в файл

     #!/bin/bash exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line" >> foo.log; done;) echo "some script commands" /path-to/some-thrid-party-programs 
  • Или печатать временную метку и записывать в stdout

     #!/bin/bash exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line"; done;) echo "some script commands" /path-to/some-thrid-party-programs 

    затем сохраните их в настройках /etc/crontab

     * * * * * root /path-to-script/foo.sh >> /path-to-log-file/foo.log 

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

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

Pushmonstats.sh – это сценарий, который собирает статистику температуры системы на моем ПК и отправляет ее в малину Pi, на которой работает Cacti. Некоторое время назад сеть застряла. Я только получил тайм-ауты SSH в журнале ошибок. К сожалению, в этом журнале нет записей времени. Я не знал, как добавить отметку времени к записи журнала. Итак, после некоторых поисков в Интернете я наткнулся на этот пост, и это то, что я сделал с помощью ts .

Чтобы проверить его, я использовал неизвестный вариант rand . Это дало ошибку stderr. Чтобы захватить его, я перенаправляю его во временный файл. Затем я использую cat, чтобы показать содержимое файла и передать его в ts , добавить формат времени, который я нашел в этом сообщении, и, наконец, зарегистрировать его в файле ошибки. Затем я очищаю содержимое временного файла, иначе я получаю двойные записи для одной и той же ошибки.

Crontab:

 * * * * * /home/monusr/bin/pushmonstats.sh 1>> /home/monusr/pushmonstats.log 2> /home/monusr/.err;/bin/cat /home/monusr/.err|/usr/bin/ts %F-%H:%M:%.S 1>> /home/monusr/pushmonstats.err;> /home/monusr/.err 

Это дает следующее в моем журнале ошибок:

 2014-03-22-19:17:53.823720 rand: unknown option -- '-l' 

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

Interesting Posts

Стойкая функция blockdev setra для чтения вперед

Не удалось обновить / обновить пакет Oh-My-Zsh с помощью команды `sudo pacman -S Oh-My-Zsh`

Минимизировать PHP.CGI.Argument.Injection и дальнейшее упрощение веб-сервера Centos 6.4

команда mount для команды пользовательского пространства или команды ядра

Ограничить пользователей SFTP разными каталогами

Проблема с беспроводной локальной сетью на Linux Mint

Почему знак «меньше» не работает в качестве замены кошки в bash?

SFTP chroot jail / access на основе шаблона

Открыть интерактивный текст в emacs в новом / соседнем окне

Поиск файлов в каталоге с парными именами

Не удалось найти вариант Win 10 при загрузке после установки Linux Mint

Настройка nginx для моих собственных целей

awk распечатать совпадение, только если последняя запись перед другим совпадением

Как расширить псевдонимы bash

Gnome3 +: Как удалить избранное из Dash через терминал?

Linux и Unix - лучшая ОС в мире.