Там, где есть необходимость, есть способ!Я думаю, что это хороший урок для bash, чтобы увидеть, как работает управление процессами и ipc.Лучшее решение, конечно, Expect.Но настоящая причина в том, что каналы могут быть хитрыми, и многие команды предназначены для ожидания данных, а это означает, что процесс станет зомби по причинам, которые трудно предсказать.Но изучение того, как и почему напоминает нам о том, что происходит под капотом.
Когда в процессе участвуют два процесса, существует опасность того, что один или оба попытаются прочитать данные, которые никогда не поступят.Правила помолвки должны быть кристально чистыми.Такие вещи, как CRLF и кодировка символов, могут убить вечеринку.К счастью, двух близких партнеров, таких как bash-скрипт и его дочерний процесс, относительно легко поддерживать.Проще всего упустить то, что bash запускает дочерний процесс практически для каждого, что он делает.Если вы можете заставить его работать с bash, вы хорошо знаете, что делаете.
Дело в том, что мы хотим поговорить с другим процессом.Вот сервер:
# a really bad SMTP server
# a hint at courtesy to the client
shopt -s nocasematch
echo "220 $HOSTNAME SMTP [$$]"
while true
do
read
[[ "$REPLY" =~ ^helo\ [^\ ] ]] && break
[[ "$REPLY" =~ ^quit ]] && echo "Later" && exit
echo 503 5.5.1 Nice guys say hello.
done
NAME=`echo "$REPLY" | sed -r -e 's/^helo //i'`
echo 250 Hello there, $NAME
while read
do
[[ "$REPLY" =~ ^mail\ from: ]] && { echo 250 2.1.0 Good guess...; continue; }
[[ "$REPLY" =~ ^rcpt\ to: ]] && { echo 250 2.1.0 Keep trying...; continue; }
[[ "$REPLY" =~ ^quit ]] && { echo Later, $NAME; exit; }
echo 502 5.5.2 Please just QUIT
done
echo Pipe closed, exiting
Теперь сценарий, который, мы надеемся, совершает чудеса.
# Talk to a subprocess using named pipes
rm -fr A B # don't use old pipes
mkfifo A B
# server will listen to A and send to B
./smtp.sh < A > B &
# If we write to A, the pipe will be closed.
# That doesn't happen when writing to a file handle.
exec 3>A
read < B
echo "$REPLY"
# send an email, so long as response codes look good
while read L
do
echo "> $L"
echo $L > A
read < B
echo $REPLY
[[ "$REPLY" =~ ^2 ]] || break
done <<EOF
HELO me
MAIL FROM: me
RCPT TO: you
DATA
Subject: Nothing
Message
.
EOF
# This is tricky, and the reason sane people use Expect. If we
# send QUIT and then wait on B (ie. cat B) we may have trouble.
# If the server exits, the "Later" response in the pipe might
# disappear, leaving the cat command (and us) waiting for data.
# So, let cat have our STDOUT and move on.
cat B &
# Now, we should wait for the cat process to get going before we
# send the QUIT command. If we don't, the server will exit, the
# pipe will empty and cat will miss its chance to show the
# server's final words.
echo -n > B # also, 'sleep 1' will probably work.
echo "> quit"
echo "quit" > A
# close the file handle
exec 3>&-
rm A B
Обратите внимание, что мы не просто выводим команды SMTP на сервере.Мы проверяем каждый код ответа, чтобы убедиться, что все в порядке.В этом случае все будет не в порядке, и скрипт будет освобожден.