Многие знают про & и wait, но есть куда более элегантный инструмент для асинхронной работы -
coproc. Это встроенная команда, которая запускает процесс в фоне и автоматически подключает к нему двусторонний канал (pipe).❓ Как это работает
coproc создает процесс, у которого:
stdin доступен через дескриптор ${COPROC[1]} (запись в процесс);
stdout доступен через ${COPROC[0]} (чтение из процесса);
имя coproc можно задавать, чтобы управлять несколькими одновременно.
▪️ Простейший пример
#!/bin/bash
# Запускаем фоновый bc как "асинхронный калькулятор"
coproc CALC { bc -l; }
# Отправляем в stdin команды
echo "2+3" >&"${CALC[1]}"
echo "s(1)" >&"${CALC[1]}"
# Читаем ответы из stdout
read -u "${CALC[0]}" result1
read -u "${CALC[0]}" result2
echo "Результат 1: $result1"
echo "Результат 2: $result2"
Процесс bc живет, пока вы его не закроете. То есть можно посылать команды и читать ответы несколько раз.
▪️ Практические кейсы
📍 Асинхронные задачи с обратной связью. Можно запускать ping, tcpdump или tail -f в coproc, а потом считывать поток строк построчно:
coproc PINGER { ping -O 8.8.8.8; }
while read -ru "${PINGER[0]}" line; do
echo "PING: $line"
done
📍 Фоновый обработчик. Например, пишем строки в процессинг-скрипт:
coproc HANDLER { while read line; do echo ">> $line"; done; }
echo "Hello" >&"${HANDLER[1]}"
echo "World" >&"${HANDLER[1]}"
📍 Несколько процессов. Coproc можно называть:
coproc P1 { ping -c2 8.8.8.8; }
coproc P2 { ping -c2 1.1.1.1; }
▪️ Подводные камни
Каналы буферизуются, иногда нужно sleep или stdbuf -oL для построчной работы.
Закрывайте дескрипторы exec {fd}>&-, иначе процесс может висеть.
coproc работает только в bash ≥ 4.
BashTex 📱 #bash #utils