Фоновый процесс перенаправить на 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 сказано, что он не поддерживается.
И, как обсуждалось в другом месте, помните об ограничениях совместного использования каналов между процессами.