Нужен скрипт для перенаправления STDIN & STDOUT на именованные каналы
У меня есть приложение, которое запускает помощник аутентификации (мой сценарий) и использует STDIN/STDOUT для связи.
Я хочу перенаправить STDIN и STDOUT из этого скрипта в два именованных канала для взаимодействия с другой программой.
Например:
SCRIPT_STDIN> pipe1 Вот поток, который я пытаюсь выполнить: [Приложение] -> Запускает вспомогательный скрипт, пишет в помощники STDIN, читает из помощников STDOUT (пример: STDIN: имя пользователя, пароль; STDOUT: LOGIN_OK) Команда cat может делать почти то, что я хочу. Если бы была возможность скопировать STDIN в STDERR, я мог бы заставить cat сделать это с помощью команды (предполагая, что вымышленная опция -e echos для STDERR вместо STDOUT): cat -e PIPE2 2> PIPE1 (чтение из PIPE2 и запись его в STDOUT, копирование ввода, обычно переход в STDERR в PIPE1)
SCRIPT_STDOUT
[Helper Script] -> Считывает STDIN (данные из приложения), пересылает в PIPE1; читает из PIPE2, пишет, что обратно в приложение на STDOUT
[Другой процесс] -> Считывает из ввода PIPE1, обрабатывает и возвращает результаты в PIPE2
2 ответа
Мой предыдущий ответ не был идеальным решением, как я позже обнаружил. У него есть три ошибки: одна не закрывается при закрытии stdin (eof on stdin). Во-вторых, 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 и выводит его в PIPE1, а также берет из PIPE2 и выводит в STDOUT.
#!/bin/ksh
exec 3>../pipes/PIPE1
exec 4<../pipes/PIPE2
{ cat; } <&4 >&1 &
{ cat; } <&0 >&3
wait
Цель этого состоит в том, чтобы перенаправить ввод / вывод для вспомогательного приложения на два канала, которые могут обрабатываться сторонним приложением (это типичный помощник аутентификации).