如何在主Shell中判断FIFO就绪以读取子Shell更新的变量值
问题:Shell中判断FIFO就绪可读取的条件
我有一个主Shell,运行期间需要在后台调用update_bk函数,用来更新主Shell后续会用到的变量VarA。因为后台运行的函数是子Shell,它对VarA的更新没法被主Shell感知,所以用mkfifo来解决这个问题。
update_bk函数代码
update_bk(){ local VarB mkfifo ${update_bg_fifo} until [[ Condition ]] do VarB=$(otherFunction) sleep 5 done echo ${VarB} > ${update_bg_fifo} && rm ${update_bg_fifo} }
主Shell代码
Until [condition] do [condition 1] to check if ${update_bg_fifo} is ready, and cat it to the VarA some thing job2 [condition 3] && [ ! -P ${update_bg_fifo} ] to do call (update_bk) $ (when contion3 is true and no existing update_bk is running) done
核心疑问
我现在的问题是,怎么编写主Shell中的[condition 1]来判断${update_bg_fifo}已就绪可读取?目前用[-p ${update_bg_fifo}]作为判断条件,但执行cat ${update_bg_fifo}时会一直等待update_bk()完成写入操作。
解决方案
首先明确:FIFO的本质特性是,cat操作会阻塞直到有进程打开它进行写入——哪怕FIFO文件已经存在。你当前的问题不是FIFO没就绪,而是update_bk要等到Condition满足才会写入数据,导致cat一直等待。
这里提供两种实用解决思路:
1. 让update_bk循环内持续写入FIFO
修改update_bk,把写入操作放到循环内部,这样主Shell就能实时读到更新后的VarB,无需等到循环结束:
update_bk(){ local VarB mkfifo ${update_bg_fifo} # 退出时自动清理FIFO,避免残留 trap 'rm -f ${update_bg_fifo}' EXIT until [[ Condition ]] do VarB=$(otherFunction) # 每次循环都写入最新值 echo ${VarB} > ${update_bg_fifo} sleep 5 done # 写入结束标记,供主Shell识别 echo "__UPDATE_FINISHED__" > ${update_bg_fifo} }
主Shell中用timeout配合读取,避免无限制阻塞:
# condition1 实现逻辑 if [ -p "${update_bg_fifo}" ]; then # 尝试读取FIFO,超时1秒防止阻塞主流程 if VarA=$(timeout 1 cat "${update_bg_fifo}"); then # 判断是否是结束标记 if [ "${VarA}" = "__UPDATE_FINISHED__" ]; then # 清理FIFO标记 unset update_bg_fifo fi fi fi
2. 结合lsof检查FIFO的写入状态
用lsof检查FIFO是否被写入进程打开,确保有数据可读时再执行cat:
# condition1 实现逻辑 if [ -p "${update_bg_fifo}" ] && lsof -t -w "${update_bg_fifo}" | grep -q .; then VarA=$(cat "${update_bg_fifo}") fi
注意:lsof可能需要额外安装,且频繁调用会有轻微性能开销,适合对实时性要求不高的场景。
内容的提问来源于stack exchange,提问作者seanlv
相关产品推荐
相关产品推荐

