Bash中使用exec通过变量关闭文件描述符报not found错误
问题根因
报错核心是Shell命令解析顺序的优先级规则:Shell会先识别命令里的重定向语法,再执行变量展开。
你写exec $fd<&-时,Shell在重定向解析阶段看到<&-前面是变量$fd而非字面量数字,就不会把这段识别为关闭文件描述符的重定向操作。等变量展开完成后,整行被解析为exec 25 <&-,25被当成exec要执行的外部命令,Shell找不到名为25的可执行文件,就抛出exec: 25: not found错误。
另外你的fd存储逻辑还有隐藏bug:Bash数组追加元素的写法错误,fds+=$pfd不会新增数组元素,只会把$pfd拼接到数组第一个元素末尾,后续循环读取时会拿到拼接后的错误fd值。
修复方案
1. 修正数组追加语法
把原有fds+=$pfd替换为标准数组追加写法,保证每个fd作为独立元素存储:
fds+=("$pfd")
2. 动态操作文件描述符的正确写法
由于重定向解析早于变量展开,动态指定fd编号时需要用eval提前构造完整命令,让Shell能正确识别重定向规则:
修复后的fd关闭逻辑
for fd in "${fds[@]}"; do echo "Closing fd $fd and remove pipes" eval "exec $fd<&-" rm -f "pipe$fd" done
如果关闭的是写端文件描述符,把
<&-替换为>&-即可,和你打开fd时的读写方向保持一致。
修复后的fd创建逻辑参考
pfd=25 # 从25开始分配fd,避开程序自身占用的描述符 fds=() mkfifo "pipe$pfd" eval "exec $pfd>pipe$pfd" fds+=("$pfd") pfd=$((pfd + 1))
内容的提问来源于stack exchange,提问作者Remy
相关产品推荐
相关产品推荐

