我试图在shell脚本中建立与IMAP服务器的连接.虽然我可以连接并发出命令,但是合适地关闭连接似乎是不可能的.
这是我正在使用的测试命令:
openssl s_client -crlf -connect server:993 <<EOF
01 login USERNAME PASSWORD
02 LIST "" "*"
03 logout
EOF
Run Code Online (Sandbox Code Playgroud)
因为一旦输入用完就连接关闭,这会在收到任何输出之前发生,因此我从未收到所需的数据.
如果我添加选项-ign_eof
选项,以便忽略输入结束以保持连接打开,则根据需要返回输出.但是在连接关闭之后......
* BYE Logging out
03 OK Logout completed.
Run Code Online (Sandbox Code Playgroud)
... 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."
Run Code Online (Sandbox Code Playgroud)
该脚本使用一个参数调用自身,以输出通过管道连接到openssl的IMAP命令,其输出通过管道传输到read
循环中,以便进行处理.MYFLAG变量仅用于隐藏openssl输出的信息,只是回显服务器连接的输出.
我选择一个虚拟文件夹名称,其中包含脚本第二个实例的PID作为一种传递回来的方法,显然临时文件会更好但是对于测试我想保持一切自包含并能够看到什么正在发生.
一旦显示获取信息并且服务器返回OK响应,它就会向脚本的第二个实例发送SIGUSR1信号,然后发送注销消息并退出,关闭stdin,导致s_client断开连接.
最初我将04 logout
命令包含在初始回声集中,但是当我这样做时,只有fetch输出然后停止显示读取循环,它甚至没有显示操作的OK状态,尽管收到了所有内容.
此外,我需要使用tr
去除尾随回车,但如果我管道输出从openssl到那么读循环没有收到任何东西.
你可以通过计时输入openssl来解决这个问题.我能想出的最简单的方法是使用一个回显stdout输入的函数:
#!/bin/sh
imapscript () {
echo '01 login USER PASSWD'
echo '02 LIST "" "*"'
echo '03 logout'
while sleep 1; do
echo "04 logout"
done
}
imapscript | openssl s_client -crlf -connect server:993
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4788 次 |
最近记录: |