Есть ли инструмент для динамического перенаправления вывода в новый файл по запросу

8

В настоящее время я перенаправляю вывод инструмента мониторинга в файл, однако я хотел бы перенаправить этот вывод в новый файл по моему запросу (используя привязку клавиш), не останавливая указанный инструмент.

Что-то вроде

monitor_program | handle_stdout

Где handle_stdoutпозволяет мне определить новый файл, куда поместить журнал в определенной точке.

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

Тревиньо
источник
Вероятно, вы можете запустить logrotateпользовательский конфигурационный файл вручную, в зависимости от поведения вашей monitor_program, но это несколько странно.
Ульрих Шварц
Кажется, что ваше редактирование на самом деле является ответом на вопрос. В этом случае, пожалуйста, опубликуйте его как ответ (самостоятельные ответы приветствуются!) И удалите ответ из своего вопроса.
кошка

Ответы:

9

Я предложу именованную трубу.

  1. Создайте канал mkfifo p(назовите его как хотите, если не 'p')

  2. Создайте скрипт «reader», который читает из канала и пишет где угодно

  3. Скажите программе мониторинга, чтобы она записывала свои логи в именованный канал

Вот пример сценария чтения, который читает из именованного канала 'p' и записывает данные в индексированный файл 'mylog':

#!/bin/sh

INDEX=0

switchlog() {
  read INDEX < newindex
  echo now writing to "mylog.$INDEX"
}

trap switchlog USR1

while :
do
  cat p >> mylog."$INDEX"
done
Джефф Шаллер
источник
2
Вы также можете перехватить сигнал (например, USR1) в скрипте считывателя как сигнал для переключения журналов.
Джефф Шаллер
Это начинает быть чем-то, что мне нужно ... Однако скрипт для чтения должен иметь возможность изменять вывод, основываясь на моем kebinding. И, возможно, попросите у меня новое имя файла для использования (хотя это необязательно, даже последовательные имена журналов подойдут)
Тревиньо
Я отредактировал пример сценария, чтобы показать пример переключения журнала с помощью kill -USR1. введите новый номер в файл 'newindex', чтобы он мог его забрать.
Джефф Шаллер
1
просто еще одна идея - если вы оставите окно открытым для запуска скрипта «reader», вы можете перехватить «INT» вместо USR1 и просто нажать Control-C в этом окне, чтобы уведомить его о новом имени файла журнала.
Джефф Шаллер
1
Почему, readа printfне просто cat <p >> mylog."$INDEX"?
Wildcard
7

Основываясь на своей идее SIGINT, здесь с помощью SIGQUIT ( Ctrl+\) вы все равно можете использовать, Ctrl+Cчтобы остановить все это:

(trap '' QUIT; monitor_command) | (
   trap : QUIT
   ulimit -c 0 # prevent core dump so SIGQUIT behaves like SIGINT
               # for cat
   n=0; while n=$((n+1)); file=output.$n.log; do
     printf 'Outputting to "%s"\n' "$file"
     cat > "$file"
   done)

Это предполагает, что catэто не встроенная функция в вашей оболочке (поэтому она прерывается при нажатии Ctrl+\).

Обратите внимание, что, как и в вашем подходе, есть вероятность, что SIGQUIT будет доставлен в неправильное время (в системном вызове write), что приведет к потере некоторых данных.

Стефан Шазелас
источник
1

Вы могли бы, вероятно, использовать lessи сохранить оттуда, набрав sзатем имя файла, в который вы хотите сохранить, затем Enter. От Как мне записать все строки из меньшего в файл? ,

BenjaminH
источник
К сожалению, невозможно использовать больше файлов журналов, после того как вы установили один, вы не можете переопределить новый. Также вы не можете очистить журнал после того, как сделали. Итак ... Хорошая отправная точка (спасибо), но пока недостаточно.
Тревиньо
0

Не зная больше о вашем «запросе», на него невозможно ответить. Если бы он был основан на размере файла или интервале, то rotatelogs (который должен идти в комплекте с Apache httpd) работал бы.

symcbean
источник
Извините, я не сказал этого явно, я предполагаю связывание клавиш, которое позволило бы изменить имя журнала.
Тревиньо
0

Благодаря ответу Джеффа Шаллера у меня получилось что-то вроде этого, которое в основном делает то, что мне нужно, назовем это так reader.sh:

#!/bin/sh

INDEX=0
LOGNAME="$INDEX.log"

switchlog() {
  local custom_name
  read -p "Add log name: " custom_name
  INDEX=$((INDEX+1))
  LOGNAME="$(printf "%03d" $INDEX).$custom_name.log"
  echo now writing to $LOGNAME
}

trap switchlog INT
switchlog

while :
do
  read foo < p
  printf "%s\n" "$foo" >> "$LOGNAME"
done

Затем речь идет о создании именованного канала с mkfifo pиспользованием двух терминалов, где monitor_program > pи reader.shработают. Затем я могу остановить читателя, чтобы установить новый журнал, используя Ctrl+ C, и ввести новое имя. Ctrl+ Z, как обычно, чтобы остановить и убить его.

Тревиньо
источник