Сценарий оболочки: перенаправить вывод программы на изменение файлов - PullRequest
0 голосов
/ 05 июня 2018

Моя цель:

Я бы хотел перенаправить вывод stdout моей программы foo в изменяющийся выходной файл в зависимости от времени выполнения программы.

Сама программа foo прослушивает bsd-сокет для получения пакетов и отображает информацию, содержащуюся в них.
Поэтому, по сути, после запуска программы foo в течение 10 минут, я хотел бы иметьstdout вывод

  • первой минуты внутри файла bar_0.dat
  • второй минуты внутри файла bar_1.dat
  • 10-я минута внутри файла bar_9.dat

Возможно ли добиться этого в сценарии оболочки и, если да, как я могу это сделать?

ЧтоМне удалось до сих пор:

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

#!/bin/bash
for i in {0..9}
do
  timeout 60s foo > "bar_${i}.dat"
done

Однако яхочу, чтобы программа foo работала непрерывно и не нуждалась в перезапуске, потому что, как я понял, я теряю некоторые прибывающие пакеты (между запущенными экземплярами существует промежуток в 20-30 мс).

Ответы [ 3 ]

0 голосов
/ 05 июня 2018

Вы можете использовать бесконечный цикл и метку даты / времени для имени файла:

while true
do
    #This date/time stamp is month_day_hour_minute all numbers
    filename="bar_$(date "+%m_%d_%H_%M").dat"
    foo > $filename 2>> error_log
    sleep 60
done

Также добавлен журнал ошибок для любых сообщений об ошибках.Не уверен, как ваша программа обрабатывает stderr.

0 голосов
/ 06 июня 2018

Позвольте программе записать в именованный канал (fifo), а затем взять вывод из этого канала и поместить его в файлы.В этом примере я запускаю цикл в фоновом режиме, а затем немедленно начинаю запись в именованный канал:

mkfifo thepipe

for (( i = 0; i < 10; ++i )); do
    timeout 60 cat thepipe >"bar_$i.dat"
done &

foo >thepipe
rm -f thepipe

В качестве альтернативы, используя подстановку процесса:

foo > >( 
    for (( i = 0; i < 10; ++i )); do
        timeout 60 cat >"bar_$i.dat"
    done
)
0 голосов
/ 05 июня 2018

Если foo производит вывод текста, вы можете получить что-то вроде:

#!/bin/bash

stamp=0
i=0
redirect() {
        if test "$(date +%s)" -gt "$((stamp + 60))"; then
                stamp=$(date +%s)
                exec > "bar_$((i++)).dat"
        fi
}
redirect
./foo | while read line; do
        echo "$line"
        redirect
done

Если foo не производит вывод текста, вы, вероятно, захотите написать foo, чтобы он принимал внешний ввод(например, сигнал) и перенаправляет вывод самостоятельно.Или вы можете просто использовать logrotate.

...