Как продублировать поток и обработать обе части потоковым способом?

Как продублировать поток и обработать обе части потоковым способом?

Иногда мне нужно вставить что-то в конвейер для отчетности или какого-то другого вторичного использования. Это может быть что-то простое, как wc -l, или что-то более сложное, как awkили даже скрипт на Python. Было бы неплохо запустить конвейер так:

zcat my_data_file.gz \
| wc -l > /tmp/linecount
| process_data.py

Проблема в том, что большинство утилит не выводят данные в stdout. teeМожно записать данные во временный файл, но тогда придется ждать, пока все будет сделано:

zcat my_data_file.gz \
| tee /tmp/f \
| process_data.py && \
wc -l /tmp/f > /tmp/linecount && rm /tmp/f

Это не оптимально: это может быть очень длительный конвейер; я могу захотеть увидеть промежуточные результаты от аналога раньше wc; и я могу не захотеть хранить все данные во временном файле.

решение1

Для этого можно использовать teeи обрабатывать замену :>(...)

zcat my_data_file.gz |

# Count number of lines in stream
tee >(wc -l > /tmp/linecount) |

# Further processing
process_data.py

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

решение2

Это не совсем эффективно, но вы можете этого добиться с помощьюименованные каналы, который вы можете создать с помощьюmkififo(1)

Для примера в вопросе:

mkfifo /tmp/f

wc -l /tmp/f > /tmp/linecount &

zcat my_data_file.gz \
| tee /tmp/f \
| process_data.py &

wait

rm /tmp/f

Обратите внимание на &добавление к обоим wcи конвейеру; это означает, что оболочка переведет задачи в фоновый режим. Затем вызов waitожидает завершения всех фоновых задач. Оба процесса завершатся примерно в одно и то же время.

Помните, что если один из ваших процессов работает существенно медленнее, это может существенно замедлить весь процесс, поскольку teeможет заблокировать либо его канал stdout, либо именованный канал, в который он записывает данные.Редактировать: Кроме того, теперь у него больше режимов отказа, так как тройник выйдет из строя из-за поломки трубы, если ваш вторичный процесс выйдет из строя.

Связанный контент