Pokud vašemu příkazu nezáleží na tom, jak rychle jej zadáte, a ve skutečnosti nepotřebujete interagovat s ním, pak můžete použít heredoc.
Příklad:
#!/bin/bash
prog <<EOD
cmdx
save filex
cmdy
save filey
q
EOD
Pokud potřebujete větvení na základě výstupu programu nebo pokud je váš program vůbec citlivý na časování vašich příkazů, pak je Expect to, co chcete.
Doporučuji použít Expect. Tento nástroj je navržen pro automatizaci interaktivních aplikací shellu.
Kde je potřeba, tam je cesta! Myslím, že je to dobrá lekce bash, abyste viděli, jak funguje procesní řízení a ipc. Nejlepším řešením je samozřejmě Expect. Ale skutečným důvodem je, že roury mohou být složité a mnoho příkazů je navrženo tak, aby čekaly na data, což znamená, že se proces stane zombie z důvodů, které lze jen těžko předvídat. Ale zjistit, jak a proč, nám připomíná, co se děje pod kapotou.
Když se dva procesy zapojí do konverzace, existuje nebezpečí, že se jeden nebo oba pokusí přečíst data, která nikdy nedorazí. Pravidla zapojení musí být křišťálově jasná. Věci jako CRLF a kódování postav mohou zničit party. Naštěstí jsou dva blízcí partneři, jako je bash skript a jeho podřízený proces, relativně snadno udržovat v souladu. Nejjednodušší věc, kterou přehlédnete, je, že bash spouští podřízený proces téměř pro každou věc, kterou dělá. Pokud dokážete, aby to fungovalo s bashem, dobře víte, co děláte.
Jde o to, že chceme mluvit s jiným procesem. Zde je server:
# 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
Nyní skript, který doufejme dělá kouzlo.
# 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
Všimněte si, že na server jednoduše neukládáme příkazy SMTP. Kontrolujeme každý kód odpovědi, abychom se ujistili, že je vše v pořádku. V tomto případě nebude vše OK a scénář bude kauce.