Одной из новых функций Bash 4.0 является coproc. Оператор coproc позволяет создать сопроцесс, который взаимодействует с оболочкой по двум каналам: один для отправки данных в сопроцесс и один для получения данных от сопроцесса.
Впервые я нашел этому применение при попытке записать журнал с использованием перенаправления.
руководитель .
Цель заключалась в том, чтобы при необходимости разрешить запись вывода сценария в файл журнала после запуска сценария (например, из-за опции --бревно командная строка).
Основная проблема с протоколированием вывода после запуска сценария заключается в том, что его вывод уже мог быть перенаправлен (в файл или канал).
Если мы перенаправим уже перенаправленный вывод, мы не сможем выполнить команду так, как задумал пользователь.
Предыдущая реализация была выполнена с использованием именованных каналов:
Из прошлого статьи :#!/bin/bash echo hello if test -t 1; then # Stdout is a terminal. exec >log else # Stdout is not a terminal. npipe=/tmp/$$.
tmp trap "rm -f $npipe" EXIT mknod $npipe p tee <$npipe log & exec 1>&- exec 1>$npipe fi echo goodbye
Здесь, если стандартный поток вывода скрипта не подключен к терминалу, мы создаем трубка (именованный канал, расположенный в файловой системе), используя мкнод , и с помощью ловушка мы удаляем его, когда скрипт завершает работу.Мы можем сделать то же самое с совместными процессами:Затем мы бежим тройник , который в фоновом режиме связывает входной поток с созданным каналом.
Не забудь об этом тройник Помимо записи всего полученного из входного потока в файл, он еще и выводит все в стандартный поток вывода.
Также помните, что выходной поток тройник направляется в то же место, что и весь вывод скрипта (вызывающий скрипт тройник ).
Таким образом, вывод тройник в конечном итоге окажется там, где в данный момент направлен выходной поток сценария (то есть в перенаправленный пользователем поток вывода или конвейер, указанный при вызове сценария в командной строке).
Таким образом, мы получаем стандартный вывод тройник куда нам это нужно: в определяемый пользователем канал перенаправления или конвейера.
echo hello
if test -t 1; then
# Stdout is a terminal.
exec >log
else
# Stdout is not a terminal.
exec 7>&1
coproc tee log 1>&7
#echo Stdout of coproc: ${COPROC[0]} >&2
#echo Stdin of coproc: ${COPROC[1]} >&2
#ls -la /proc/$$/fd
exec 7>&-
exec 7>&${COPROC[1]}-
exec 1>&7-
eval "exec ${COPROC[0]}>&-"
#ls -la /proc/$$/fd
fi
echo goodbye
echo error >&2
Если наш стандартный вывод поступает на терминал, мы просто используем руководитель чтобы перенаправить наш вывод в нужный файл журнала.
Если вывод не связан с терминальным устройством, то для запуска используем coproc. тройник как совместный процесс и перенаправить наш вывод на вход тройник и выйти тройник перенаправляем туда, где изначально планировалось.
Запуск тройник использование coproc по сути работает так же, как tee в фоновом режиме (например, тройник и ), главное отличие в том, что к нему подключены оба канала (входной и выходной).
По умолчанию, Баш помещает файловые дескрипторы этих каналов в массив КОПРОК .
- КОПРОК[0] это файловый дескриптор канала, подключенного к стандартному выводу сопроцесса;
- КОПРОК[1] подключен к стандартному входу совместного процесса.
Обратите внимание на часть сценария, где вывод сценария не подключен к терминалу.
Следующая строка дублирует наш стандартный вывод в файловый дескриптор 7. exec 7>&1
Затем мы начинаем тройник его вывод перенаправляется в файловый дескриптор 7. coproc tee log 1>&7
Сейчас тройник запишет все, что прочитает из стандартного ввода, в файл с именем бревно и файловый дескриптор 7, который является нашим текущим стандартным выводом.
Теперь мы закроем файловый дескриптор 7 (помните, что тройник также «файл», который открывается в 7 как стандартный вывод): exec 7>&-
Поскольку мы закрыли 7, мы можем использовать его снова, поэтому мы перемещаем канал, подключенный к входу 7. тройник : exec 7>&${COPROC[1]}-
Затем мы перемещаем наш стандартный вывод в канал, подключенный к стандартному входу.
тройник (наш файловый дескриптор равен 7) через: exec 1>&7-
И, наконец, закрываем канал, подключенный к выходу тройник , так как он нам больше не нужен: eval "exec ${COPROC[0]}>&-"
В этом случае оценивать здесь необходимо, потому что в противном случае Баш считает, что ценность ${КОПРОК[0]} это команда.
С другой стороны, это и не требуется выше ( exec 7> &${COPROC[1]}- ), потому что Баш знает, что «7» инициирует операцию с файловым дескриптором и не считается командой.
Также обратите внимание на закомментированную строку: #ls -la /proc/$$/fd
Это полезно для просмотра файлов, открытых текущим процессом.
Теперь мы достигли желаемого эффекта: наш стандартный вывод будет направлен на тройник .
ты тройник есть «вход» в наш лог-файл и запись идет как в тот канал, так и в тот файл, который планировался изначально.
Никаких других задач для сопроцессов, по крайней мере не надуманных, я пока придумать не могу.
См.
страницу мужик ругается для получения дополнительной информации о совместных процессах.
Теги: #*nix #Системное администрирование #bash #coproc
-
Спевсипп Афинский
19 Oct, 24 -
Как Раздавать Приглашения В Google+
19 Oct, 24 -
Как Мы Показываем Дизайн Сайта Клиенту
19 Oct, 24 -
Новый Мини От Dell
19 Oct, 24