You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本多次读取OpenSSL输出管道时冻结,如何解决?

解决OpenSSL管道二次读取冻结问题

问题场景

使用OpenSSL的s_client命令连接XMPP服务器,通过两个命名管道$topipe和$frompipe分别传递输入和输出。首次从$frompipe读取服务器响应正常,但二次读取时脚本冻结,相关代码如下:

openssl s_client \
    -starttls xmpp \
    -xmpphost "$domain" \
    -connect "$host:$port" \
    -quiet \
    < $topipe \
    > $frompipe &

echo "somedata" > $topipe

# 第一次读取正常
read -t 1 serverresponse < "$frompipe"

# 中间处理逻辑...

# 此处冻结
read -t 1 serverresponse < "$frompipe"

问题原因

每次执行read < "$frompipe"时,Bash会临时打开管道的读端,读取完成后立即关闭该读端。当第一次读取完成并关闭读端后,管道$frompipe的所有读端都已关闭,此时OpenSSL进程向管道写入数据时会触发SIGPIPE信号,导致OpenSSL进程直接终止。第二次读取时,管道已没有活跃的写进程,脚本会陷入等待状态(即便设置了超时也可能出现异常阻塞)。

另外,echo "somedata" > $topipe写完后会立即关闭$topipe的写端,可能导致OpenSSL的stdin收到EOF,提前终止进程,也会引发后续读取问题。

解决方案

1. 持久化管道文件描述符

通过exec命令提前打开管道的读/写文件描述符,保持管道两端持续打开,避免多次打开关闭导致的进程终止:

# 先创建命名管道(如果还没创建)
mkfifo topipe frompipe

# 打开frompipe的读端到文件描述符3
exec 3<"$frompipe"
# 打开topipe的写端到文件描述符4
exec 4>"$topipe"

# 启动OpenSSL进程
openssl s_client \
    -starttls xmpp \
    -xmpphost "$domain" \
    -connect "$host:$port" \
    -quiet \
    <&4 \
    >&3 &

# 通过持久化描述符写入数据
echo "somedata" >&4

# 第一次读取
read -t 1 serverresponse <&3

# 中间处理逻辑...

# 第二次读取(正常工作)
read -t 1 serverresponse <&3

# 最后关闭文件描述符
exec 3<&-
exec 4>&-

2. 在单个子shell中完成所有读取操作

将所有读取逻辑放入同一个子shell,保持管道读端持续打开,避免多次关闭读端:

mkfifo topipe frompipe

# 启动OpenSSL进程
openssl s_client \
    -starttls xmpp \
    -xmpphost "$domain" \
    -connect "$host:$port" \
    -quiet \
    < $topipe \
    > $frompipe &

# 保持topipe写端打开(避免OpenSSL提前收到EOF)
exec 4>"$topipe"
echo "somedata" >&4

# 在子shell中完成所有读取,保持frompipe读端打开
(
    read -t 1 serverresponse
    # 中间处理逻辑...
    read -t 1 serverresponse
) < "$frompipe"

exec 4>&-

内容的提问来源于stack exchange,提问作者Hid-K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:02:48