Si votre commande ne se soucie pas de la vitesse à laquelle vous lui donnez une entrée, et que vous n'avez pas vraiment besoin d'interagir avec lui, vous pouvez utiliser un heredoc.
Exemple :
#!/bin/bash
prog <<EOD
cmdx
save filex
cmdy
save filey
q
EOD
Si vous avez besoin d'un branchement basé sur la sortie du programme, ou si votre programme est du tout sensible au timing de vos commandes, alors Attendez est ce que vous voulez.
Je vous recommande d'utiliser Expect. Cet outil est conçu pour automatiser les applications shell interactives.
Là où il y a un besoin, il y a un moyen ! Je pense que c'est une bonne leçon de bash pour voir comment la gestion des processus et l'ipc fonctionnent. La meilleure solution est, bien sûr, Attendre. Mais la vraie raison est que les canaux peuvent être délicats et que de nombreuses commandes sont conçues pour attendre des données, ce qui signifie que le processus deviendra un zombie pour des raisons difficiles à prévoir. Mais apprendre comment et pourquoi nous rappelle ce qui se passe sous le capot.
Lorsque deux processus s'engagent dans une conversation, le danger est que l'un ou les deux essaient de lire des données qui n'arriveront jamais. Les règles d'engagement doivent être limpides. Des choses comme CRLF et l'encodage de caractères peuvent tuer la fête. Heureusement, deux partenaires proches comme un script bash et son processus enfant sont relativement faciles à garder en ligne. La chose la plus facile à manquer est que bash lance un processus enfant pour à peu près tout ce qu'il fait. Si vous pouvez le faire fonctionner avec bash, vous savez parfaitement ce que vous faites.
Le fait est que nous voulons parler d'un autre processus. Voici un serveur :
# 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
Maintenant, le script qui, espérons-le, fait la magie.
# 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
Notez que nous ne déversons pas simplement les commandes SMTP sur le serveur. Nous vérifions chaque code de réponse pour nous assurer que tout va bien. Dans ce cas, les choses n'iront pas bien et le script sera renfloué.