Предположим, я хочу выполнить несколько программ параллельно и объединить их результаты в один канал:
sh -c '
(echo qqq; echo qqq2; echo qqq3)&
(echo www; echo www2; echo www3)&
(echo eee; echo eee2; echo eee3)&
wait; wait; wait'
Этот подход к оболочке хорошо работает в этом простом случае, но я ожидаю, что он потерпит неудачу, если программы будут выводить все больше и более длинные строки в буферизованном виде, например так (построено):
qqq
qqwww
q2
qqq3www2
wwweee3
eee2
eee3
Одно из решений, на которое мне подсказали, было tail -f
:
tail -n +0 -q -f <(echo qqq; echo qqq2; echo qqq3) <(echo www; echo www2; echo www3) <(echo eee; echo eee2; echo eee3)
, но это неоптимальный вариант: он выводит данные вяло, он не завершается; В этом случае выходные данные отображаются не в «спящем» порядке, а в порядке аргументов:
tail -n +0 -q -f <(sleep 1; echo qqq; sleep 1; echo qqq2; echo qqq3) <(echo www; echo www2; sleep 10; echo www3) <(echo eee; sleep 4; echo eee2; echo eee3) | cat
Я реализовал специальную небольшую программу для этого, но считаю, что должен быть какой-то стандартный хороший способ сделать это.
Как это сделать с помощью стандартных инструментов (и без tail -f
недостатков)?
syslog
...syslog
не для журналов, а для чего-то нестандартного считается нормальным?-s
вариант, чем другие предложения, опубликованные до сих пор, но я подумал, что стоит упомянуть вариант хвоста. Напримерtail -f -s .1 file
, сократит задержку цикла до 0,1 секунды с 1 секунды по умолчанию.Ответы:
GNU Parallel.
Из примечаний к выпуску от августа 2013 года:
Например:
parallel --line-buffer <jobs
Где
jobs
содержится:short.sh
:long.sh
:Выход:
источник
Решение, реализующее блокировки:
Должен быть более быстрый способ создать блокировку, чем при использовании файловой системы.
источник
Я не могу придумать ничего простого, это поможет вам, если ваши строки будут настолько длинными, что одна программа будет отправлена в спящий режим до того, как она сможет, завершить запись строки в stdout.
Однако, если ваши строки достаточно короткие, чтобы их можно было полностью записать до переключения процессов, и ваша проблема в том, что генерация одной строки занимает очень много времени, вы можете буферизовать вывод с помощью чтения.
Например:
источник
Вы можете создать именованный канал с помощью
mkfifo
, сбросить весь вывод в именованный канал и отдельно прочитать из именованного канала ваши собранные данные:источник
job1
иjob2
выдает длинные (> 4096 байт) строки? Похоже, это именованный конвейерный эквивалент самого первого примера кода в Questionion.tee
, который звучит именно так, как вы хотите. Возможно, посмотрите на внутренние компонентыsyslog
или другие инструменты ведения журнала, потому что они определенно объединяют вывод из нескольких мест в один файл журнала. Блокировка вполне может быть правильным ответом, как и @emmanual.