Фоновый процесс перенаправить на COPROC

В следующем тестовом скрипте я запускаю элементарный сопроцесс, к которому echo встроенный, работает в фоновом режиме, присоединяет свой стандартный вывод:

#!/bin/bash
# TEST 1
coproc /bin/sleep 100
echo >&${COPROC[1]} &

Сценарий всегда завершается неудачей без видимой причины, выдавая вывод:

./test.sh: line 4: ${COPROC[1]}: Bad file descriptor

Интересно, должен ли правильный синтаксис быть именно таким (амперсанд перемещается перед перенаправлением):

#!/bin/bash
# TEST 2
coproc /bin/sleep 100
echo & >&${COPROC[1]}

Этот второй пример, кажется, работает, так как он сообщает об отсутствии ошибок во время выполнения, но с этим синтаксисом перенаправление не выполняется на практике; на самом деле, рассмотрим этот другой тест:

#!/bin/bash
# TEST 3
/bin/echo abc & >xfile

Тест 3 создает файл xfile, но ничего не пишет в него. Любопытно, пытаясь снова установить амперсанд после перенаправления сделать echo работают нормально:

#!/bin/bash
# TEST 4
/bin/echo abc >xfile &

Тест 4 создает файл xfile с внутри строки abc,

Имейте некоторое представление о том, что вызывает coproc ошибка перенаправления или каков правильный синтаксис?

2 ответа

Решение

У вас есть ответ в другом месте http://lists.gnu.org/archive/html/bug-bash/2012-06/msg00027.html:

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

Как отмечалось в другом месте, coproc организует закрытие своих файловых дескрипторов в подоболочках. Вы можете обойти это используя

coproc { whatever; }
exec {WHATEVER[0]}<&${COPROC[0]}- {WHATEVER[1]}>&${COPROC[1]}-

Если вы используете Bash до версии 4.3, вам придется использовать отдельные переменные для входных и выходных переменных:

exec {IN}<&${COPROC[0]}- {OUT}>&${COPROC[1]}-

Если вы используете Bash до 4.1, вам придется обходиться фиксированными номерами файловых дескрипторов:

exec 4<&${COPROC[0]}- 5>&${COPROC[1]}- ; IN=4 OUT=5

Для интерактивной оболочки вы можете рассмотреть disown,

Это соглашение также имеет преимущество, заключающееся в том, что вы можете использовать более одного сопроцесса, даже несмотря на то, что на странице руководства Bash сказано, что он не поддерживается.

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

Другие вопросы по тегам