重写Shell脚本以避免cat绕过XDG_RUNTIME_DIR存在性检查
解决FIFO驱动进程在目录消失后无法终止的问题
问题原因
你原脚本的逻辑存在缺陷:while [ -e "${XDG_RUNTIME_DIR}" ]; do cat ${FIFO} ; done中,cat ${FIFO}会持续阻塞等待FIFO输入,只有当FIFO被关闭或数据读取完成后,才会回到while循环的条件检查步骤。如果XDG_RUNTIME_DIR在cat阻塞期间被删除,循环根本没机会执行存在性检查,导致cat和下游的my_program一直挂起运行。
修复方案
方法一:后台监控目录状态,触发进程组终止
这是最可靠的方式,通过后台进程定期检查目录是否存在,一旦目录消失就终止整个进程组的所有相关进程:
#!/bin/sh # 启动后台监控进程,定期检查目录状态 ( while [ -e "${XDG_RUNTIME_DIR}" ]; do sleep 1 # 可根据需求调整检查间隔,比如改为sleep 0.5 done kill 0 # 终止当前进程组内的所有进程(包括监控进程、cat、my_program) ) & # 持续读取FIFO并传递给my_program cat "${FIFO}" | my_program
方法二:循环读取FIFO,每次读取前检查目录
如果不想依赖后台进程,可以改用逐行读取FIFO的方式,确保循环能定期回到目录存在性检查:
#!/bin/sh # 打开FIFO文件描述符 exec 3<>"${FIFO}" while [ -e "${XDG_RUNTIME_DIR}" ]; do # 读取FIFO的一行内容,读取失败则退出循环 if ! read -r line <&3; then break fi # 将内容传递给my_program echo "$line" done # 关闭文件描述符 exec 3>&- | my_program
补充说明
- 方法一中的
kill 0会向当前进程组的所有进程发送终止信号,确保所有相关进程(监控脚本、cat、my_program)都能被彻底清理。 - 方法二中的逐行读取会在每次读取后回到while条件检查,但如果FIFO长时间无数据,
read会阻塞,此时仍无法检测目录变化——这种场景下方法一更优。
内容的提问来源于stack exchange,提问作者jj_p
相关产品推荐
相关产品推荐

