Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在shell脚本中通过s_客户端关闭连接_Bash_Openssl - Fatal编程技术网

Bash 在shell脚本中通过s_客户端关闭连接

Bash 在shell脚本中通过s_客户端关闭连接,bash,openssl,Bash,Openssl,我正在尝试在shell脚本中与IMAP服务器建立连接。虽然我可以连接并发出命令,但适当地关闭连接似乎是不可能的 这是我正在使用的测试命令: openssl s_client -crlf -connect server:993 <<EOF 01 login USERNAME PASSWORD 02 LIST "" "*" 03 logout EOF …s_客户端保持活动状态,因此执行永远不会返回到脚本 是否有一种解决方案会在服务器关闭连接时导致s_客户端终止 或者是否有使用标准工具的

我正在尝试在shell脚本中与IMAP服务器建立连接。虽然我可以连接并发出命令,但适当地关闭连接似乎是不可能的

这是我正在使用的测试命令:

openssl s_client -crlf -connect server:993 <<EOF
01 login USERNAME PASSWORD
02 LIST "" "*"
03 logout
EOF
…s_客户端保持活动状态,因此执行永远不会返回到脚本

是否有一种解决方案会在服务器关闭连接时导致s_客户端终止

或者是否有使用标准工具的替代方法?该脚本将运行在MacOSX、Debian和Redhat衍生产品上,可能还有Android终端模拟器,因此我希望使用相当标准的工具来实现可移植性,而不是专门的软件包

更新:我提出了一个我并不完全满意的答案,但它确实有效。它使用一个脚本将命令传输到openssl,但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."
脚本使用一个参数调用自身,以输出IMAP命令,该命令通过管道传输到openssl,其输出通过管道传输到
read
循环中,以便对其进行处理。MYFLAG变量仅用于隐藏openssl输出的信息,并仅回显服务器连接的输出

我选择了一个虚拟文件夹名,其中包含脚本第二个实例的PID,作为一种返回的方式,显然临时文件会更好,但对于测试,我希望所有内容都是自包含的,并且能够观察发生了什么

显示获取信息并且服务器返回OK响应后,它将向脚本的第二个实例发送SIGUSR1信号,然后该脚本将发送注销消息并退出,关闭stdin,从而导致s_客户端断开连接

最初,我在最初的一组echos中包含了
04 logout
命令,但当我这样做时,读取循环仅显示到fetch输出停止时,它甚至没有显示操作的OK状态,尽管接收到了所有内容


此外,我还需要使用
tr
来剥离尾随的回车符,但是如果我通过管道从openssl输出,那么读取循环将不会接收任何内容。

您可以通过将输入计时到openssl来解决这一问题。 我能想到的最简单的方法是使用一个函数,将输入回显到标准输出:

#!/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

我有一个类似的想法,使用一个脚本来响应命令,但是我有一个无限循环来保持连接,直到接收到输入,然后我就可以杀死这个脚本。我已经用我的测试脚本更新了这个问题。不过我不确定我的解决方案有什么问题-我在debian和OSX上进行了测试,它得到的文件夹列表很好,然后退出;无需发送信号和终止,因为一旦服务器关闭连接,您尝试发送一些东西(这是循环中的
echo
,您可以随意放置,我只使用
04注销
,因为它更清楚我们真正想要做什么),
s_client
将由于套接字关闭而退出。在能够完全测试您的想法之后,这实际上要好得多。我不确定我做了什么不同的事情,但当我尝试这样做之前,有时会在
fetch1:*(BODY[HEADER.FIELDS(Subject)])的结果中途关闭连接。你的解决方案似乎每次都能奏效,这正是我想要的。谢谢
#!/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