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

为何bash脚本启动的程序在脚本后台运行时会停止(仅读命名管道stdin时)

后台运行脚本时,从命名管道读取stdin的程序停止的问题分析与解决

行为差异解释

当bar.sh前台运行时:

  • cat > pipe作为前台进程可以正常读取终端stdin,命名管道的写端保持打开状态;
  • foo.sh的stdin被重定向到管道,但它的代码逻辑中没有读取stdin的操作,因此不会触发任何终端相关的信号,持续循环打印"Running"。

当bar.sh后台运行时:

  • cat > pipe尝试读取控制终端的stdin,但后台进程组默认不允许读取终端输入,内核会向整个后台进程组(包含bar.sh、cat和foo.sh)发送SIGTTIN信号;
  • SIGTTIN信号的默认行为是暂停整个进程组,因此foo.sh被暂停,打印操作停止。

如果不将foo.sh的stdin重定向到管道:

  • foo.sh不会参与到触发SIGTTIN的进程组逻辑中,后台运行时不会收到该信号,因此可以持续正常运行。

解决方法

要让foo.sh在bar.sh后台运行时保持运行,核心是避免cat尝试读取终端stdin,从而防止SIGTTIN信号触发。以下是几种可行方案:

方案1:修改bar.sh,用轻量方式保持管道写端打开

替换依赖终端输入的cat命令,用bash内置命令: 保持管道写端打开,避免触碰终端stdin:

#!/bin/bash
rm -f pipe
mkfifo pipe
./foo.sh < pipe &
# 用内置命令保持管道写端打开,无需读取终端输入
: > pipe &
# 可选:等待后台进程,防止脚本提前退出导致管道写端关闭
wait

方案2:运行bar.sh时重定向其stdin到/dev/null

无需修改脚本,直接在运行时将脚本的stdin指向空设备,让cat从空设备读取而非终端:

./bar.sh < /dev/null &

方案3:用持续后台进程保持管道写端打开

使用tail -f /dev/null这类不依赖终端输入的进程,长期保持管道写端打开:

#!/bin/bash
rm -f pipe
mkfifo pipe
./foo.sh < pipe &
tail -f /dev/null > pipe &
wait

内容的提问来源于stack exchange,提问作者Eclogite

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:44:57