シェル スクリプト内で IMAP サーバーに接続しようとしています。接続してコマンドを発行することはできますが、接続を適切に閉じることは不可能のようです。
これは私が使用しているテストコマンドです:
openssl s_client -crlf -connect server:993 <<EOF
01 login USERNAME PASSWORD
02 LIST "" "*"
03 logout
EOF
入力がなくなるとすぐに接続が閉じられるため、これは出力が受信される前に発生するため、必要なデータを受信することはありません。
-ign_eof
接続を開いたままにするために入力終了を無視するようにオプションオプションを追加すると、必要に応じて出力が返されます。しかし、代わりに接続が閉じられた後...
* BYE Logging out
03 OK Logout completed.
...s_client は存続するため、実行がスクリプトに戻ることはありません。
サーバーが接続を閉じたときに s_client を終了させる解決策はありますか?
または、標準ツールを使用する代替方法はありますか? スクリプトは、Mac OS X、Debian、および Redhat 派生物で実行され、場合によっては Android ターミナル エミュレーターでも実行されるため、専門的なパッケージではなく、移植性のためにかなり標準的なツールを使用したいと考えています。
更新:私は完全に満足しているわけではありませんが、うまくいく答えを思いつきました. スクリプトを使用してコマンドを openssl にパイプしますが、無限ループに入り、終了するように指示する信号を受信するまで stdin を開いたままにします。ここに私のテストスクリプトがあります:
#!/bin/sh
if [ "$1" = "doit" ]; then
trap "echo \"04 logout\"; exit" SIGUSR1
echo "00 login USERNAME PASSWORD"
echo "01 SELECT PID-$$"
echo "02 SELECT FOLDER"
echo "03 FETCH 1:* (BODY[HEADER.FIELDS (Subject)])"
while :; do :; done
fi
MYFLAG=
$0 doit | openssl s_client -crlf -connect server:993 2>/dev/null | while read LINE; do
LINE=`echo "$LINE" | tr -d '\r'`
[ "${LINE:0:4}" = "* OK" ] && MYFLAG=Y
[ "${LINE:0:33}" = "01 NO Mailbox doesn't exist: PID-" ] && PID="${LINE##*PID-}"
[ "$MYFLAG" ] && echo "$LINE"
[ "$PID" -a "$LINE" = "03 OK Fetch completed." ] && kill -USR1 $PID
done
echo "Finished."
このスクリプトは、openssl にパイプされる IMAP コマンドを出力するパラメーターを使用して自身を呼び出します。このコマンドの出力は、read
処理できるようにループにパイプされます。MYFLAG 変数は、openssl による情報出力を非表示にし、サーバー接続からの出力を単にエコーするために使用されます。
これを返す方法として、スクリプトの 2 番目のインスタンスの PID を含むダミーのフォルダー名を選択します。起こっていました。
取得情報が表示され、サーバーが OK 応答を返すと、サーバーはスクリプトの 2 番目のインスタンスに SIGUSR1 シグナルを送信し、ログアウト メッセージを送信して終了し、stdin を閉じて s_client を切断します。
最初に04 logout
コマンドをエコーの最初のセットに含めましたが、これを行ったとき、読み取りループはフェッチ出力までしか表示されず、すべてが受信されたにもかかわらず、操作の OK ステータスさえ表示されませんでした。
またtr
、末尾のキャリッジ リターンを削除するために使用する必要がありますが、openssl からの出力をパイプ処理すると、読み取りループでは何も受信されません。