如何忽略FILE输入输出,仅捕获EXEC执行CMD的多行输出?
解决方案
如果你的EXEC程序支持类似echo的命令(可以输出指定字符串),那最简洁的方法是插入一个唯一标记来分隔FILE命令的输出和CMD的输出,然后用awk过滤出标记后的内容:
# 定义一个不会和正常输出冲突的唯一标记 MARKER="__CMD_OUTPUT_BEGIN__" # 合并输入流并过滤输出 CMD_OUTPUT=$( (cat "${FILE}"; echo "echo ${MARKER}"; echo "${CMD}") | "${EXEC}" | awk "/${MARKER}/{f=1; next} f" )
原理说明:
(cat "${FILE}"; echo "echo ${MARKER}"; echo "${CMD}"):把FILE内容、输出标记的命令、目标CMD合并成一个连续的输入流,传给EXEC。EXEC会依次执行FILE里的所有命令(这些输出会被awk忽略),然后执行标记命令输出我们定义的字符串,最后执行CMD并输出结果。awk "/${MARKER}/{f=1; next} f":当读取到标记字符串时,开启捕获开关并跳过标记行;之后所有输出都会被保留,也就是我们需要的CMD输出。
如果EXEC不支持自定义输出标记的命令,我们可以用FIFO结合信号控制来实现精准捕获:
#!/bin/bash # 创建临时FIFO和输出文件,脚本退出时自动清理 mkfifo exec_input trap 'rm -f exec_input cmd_output' EXIT # 启动输出处理进程:默认忽略所有输出,收到USR1信号后切换为捕获模式 { capture=0 trap 'capture=1' USR1 while IFS= read -r line; do if [ "$capture" -eq 1 ]; then echo "$line" fi done } > cmd_output & OUTPUT_HANDLER_PID=$! # 启动EXEC,输入绑定到FIFO,输出传给上面的处理进程 "${EXEC}" < exec_input >&3 3>&- & EXEC_PID=$! # 先发送FILE的内容,此时输出处理进程会忽略所有结果 cat "${FILE}" > exec_input # 发送信号通知输出处理进程开始捕获后续内容 kill -USR1 "$OUTPUT_HANDLER_PID" # 发送CMD,此时输出会被完整捕获 echo "${CMD}" > exec_input # 关闭FIFO,让EXEC收到EOF并正常退出 exec 3> exec_input exec 3>&- # 等待所有进程结束 wait "$EXEC_PID" kill "$OUTPUT_HANDLER_PID" # 将捕获的输出读取到变量中 CMD_OUTPUT=$(cat cmd_output) # 验证输出(可根据需求删除) echo "CMD的输出内容:" echo "${CMD_OUTPUT}"
原理说明:
- 用FIFO给
EXEC提供输入,确保所有命令在同一个EXEC进程中执行(保留程序运行状态)。 - 输出处理进程默认丢弃所有输出,直到收到
USR1信号后切换为捕获模式。 - 发送完FILE的内容后切换捕获模式,再发送CMD,就能精准获取CMD的输出。
你之前方案的问题分析:
你尝试的(tail -f mypipe) | ${EXEC} > somefile &无效的核心原因是:tail -f是用来持续监听文件新增内容的工具,但FIFO本身就会在有输入时供进程读取,不需要额外用tail -f——这个操作反而会打乱输入流,导致EXEC无法正确识别EOF,最终输出无法写入目标文件。
内容的提问来源于stack exchange,提问作者V0ldek
相关产品推荐
相关产品推荐

