У меня есть приложение, которое запускает помощник по аутентификации (мой скрипт) и использует STDIN / STDOUT для связи.
Я хочу перенаправить STDIN и STDOUT из этого скрипта в два именованных канала для взаимодействия с другой программой.
Например.:
SCRIPT_STDIN> pipe1
SCRIPT_STDOUT <pipe2
Вот поток, которого я пытаюсь достичь:
[Заявка] -> Запускает вспомогательный сценарий, записывает в помощники STDIN, читает из помощников STDOUT (пример: STDIN: имя пользователя, пароль; STDOUT: LOGIN_OK)
[Вспомогательный сценарий] -> Читает STDIN (данные из приложения), пересылает в PIPE1; читает из PIPE2, записывает это обратно в приложение на STDOUT
[Другой процесс] -> Читает из ввода PIPE1, обрабатывает и возвращает результаты в PIPE2
Команда cat может делать почти то, что я хочу. Если бы была возможность скопировать STDIN в STDERR, я мог бы заставить cat сделать это с помощью команды (предполагая, что фиктивный параметр -e выводит на STDERR, а не на STDOUT):
cat -e PIPE2 2> PIPE1 (читать из PIPE2 и записывать его в STDOUT, копировать ввод, обычно переход от STDERR к PIPE1)
Вот сценарий, который наконец-то делает то, что я хочу. Он считывает STDIN и выводит его в PIPE1, а берет из PIPE2 и выводит в STDOUT.
#!/bin/ksh
exec 3>../pipes/PIPE1
exec 4<../pipes/PIPE2
{ cat; } <&4 >&1 &
{ cat; } <&0 >&3
wait
Цель этого - перенаправить ввод / вывод для вспомогательного приложения на два канала, которые могут обрабатываться сторонним приложением (это типичный помощник для проверки подлинности).
Мой предыдущий ответ не был идеальным решением, как я позже обнаружил. У него есть три недостатка: во-первых, он не выключается при закрытии стандартного ввода (eof на стандартном вводе). Во-вторых, cat (и другие утилиты, такие как tee и тому подобное) имеют некоторые странные характеристики, когда дело доходит до закрытия считывающего конца канала, в который он пишет (если вы закроете и повторно откроете конец чтения канала, в который этот сценарий пишет он начнет буферизовать все данные и сбрасывать их только тогда, когда этот процесс останавливается, что явно является для меня препятствием). И в-третьих, фоновый процесс в этом случае может остаться без поддержки.
После решения этих проблем вот мой новый сценарий, который решает все три из вышеперечисленных проблем. Надеюсь, это принесет пользу кому-то.
#!/bin/ksh
#
# USAGE
# helper <path_to_CLIENT_TO_SERVER_pipe> <path_to_SERVER_TO_CLIENT_pipe>
#
CS=$1
SC=$2
exec 3>&0
trap 'exit;' CHLD
{
while read LINE; do #STDIN -> CS
print $LINE >>$CS;
done;
} <&3 &
while true; do #SC -> STDOUT
read IN <$SC;
retCode=$?
if [[ $retCode -eq 0 ]]; then
print $IN;
else
sleep 1;
fi
done
В этом случае у нас есть только один фоновый процесс, который читает stdin. Если stdin закрывается, он выйдет, и мы перехватим это и выйдем из сценария переднего плана. Сценарий переднего плана никогда не должен выходить, потому что он читает из канала, что он всегда должен делать независимо от того, что происходит на другом конце этого канала. Использование чтения, хотя и менее эффективно, не вызывает проблем с буферизацией, когда внешние процессы, которые читают / записывают в данные каналы, повышаются или останавливаются. Этот сценарий существует только тогда, когда stdin закрыт.