如何从长期运行的命令输出流中取单行输入后终止该命令?
流读取一行后立刻终止上游进程的解决方案
根因分析
你遇到的延迟退出问题是Linux管道的默认机制导致的:下游进程(如head -1)退出后,上游进程只有在尝试向已经关闭的管道写入数据时,才会收到SIGPIPE信号触发退出。你脚本里的i3-msg属于事件监听类进程,在输出第一行后会阻塞等待下一个窗口事件,直到第二个事件触发、尝试写管道时才会感知到下游已退出,因此出现了需要等第二次事件才结束的表现。
可用方案
方案1:原生Bash实现(无额外依赖,最可靠)
通过后台运行管道+进程组控制的方式,读取到第一行后主动杀死所有上游进程,无需等待下一次事件触发:
#!/bin/bash set -m # 后台运行监听管道,记录进程组ID i3-msg -t subscribe -m '["window"]' | stdbuf -o0 jq -r 'select(.change == "new") | .container.window' & PGID=$! # 读取第一行输出 read -r WIN_ID < <(tail -f --pid="$PGID" /proc/$PGID/fd/1) # 读到后立刻终止整个上游进程组 kill -TERM -"$PGID" # 你后续的业务逻辑,比如传给目标命令使用 echo "$WIN_ID" | xargs your-command
方案2:极简单行写法(适合快速使用)
用进程替换配合kill逻辑实现单行执行:
read -r WIN_ID < <(i3-msg -t subscribe -m '["window"]' | stdbuf -o0 jq -r 'select(.change == "new") | .container.window'; kill $PPID) && echo "$WIN_ID" | xargs your-command
内容的提问来源于stack exchange,提问作者HJVT
相关产品推荐
相关产品推荐

