如何编写Bash脚本连接Unix套接字待欢迎消息后读写数据?
实现方案
你之前直接通过管道发命令失效的核心原因是:管道会在套接字连接建立的同时就把指令写入,此时服务端还处于初始化握手阶段(未完成欢迎消息发送前不处理命令),因此需要先等待欢迎消息返回,确认服务端就绪后再发送隧道指令。
方案1:仅用socat实现(无额外依赖)
socat原生支持期望-发送的交互逻辑,无需安装其他工具即可满足需求:
# 基础交互命令 socat UNIX-CONNECT:data/files/monitor.socket STDOUT \ expect="Connected to soundwave server v131" \ send="tunnel r 7 localhost:22\n"
如果需要直接提取端口供后续SSH使用,可以结合grep过滤结果:
# 提取端口存到变量 TUNNEL_PORT=$(socat UNIX-CONNECT:data/files/monitor.socket STDOUT \ EXPECT="Connected to soundwave server v131" \ SEND="tunnel r 7 localhost:22\n" | grep -oP 'local port \K\d+') # 后续直接调用变量发起SSH连接 ssh -p ${TUNNEL_PORT} 你的用户名@localhost
注意:部分旧版本socat需要将
expect、send关键字替换为全大写的EXPECT、SEND,运行报错时调整即可。
方案2:用expect工具实现(适配复杂场景)
如果后续还有更多交互逻辑,可以用专门的交互处理工具expect,脚本复用性更强:
- 编写expect脚本
tunnel.exp:
#!/usr/bin/expect -f # 建立Unix套接字连接 spawn socat UNIX-CONNECT:data/files/monitor.socket STDOUT # 等待服务端返回欢迎消息 expect "Connected to soundwave server v131" # 发送隧道命令,末尾加\n模拟手动回车 send "tunnel r 7 localhost:22\n" # 匹配端口返回结果,正则提取端口 expect -re {local port (\d+)\.} # 输出端口供bash侧捕获 puts $expect_out(1,string)
- 给脚本加执行权限后,在bash中直接调用获取端口:
chmod +x tunnel.exp TUNNEL_PORT=$(./tunnel.exp) ssh -p ${TUNNEL_PORT} 你的用户名@localhost
内容的提问来源于stack exchange,提问作者Mikey A. Leonetti
相关产品推荐
相关产品推荐

