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

Shell脚本关闭文件描述符后执行echo报‘bad file descriptor’错误原因

为什么if条件后执行echo会报"bad file descriptor"错误?

这问题我太熟了!核心原因是你用exec直接关闭了标准输出(stdout,文件描述符1)或者标准错误(stderr,文件描述符2),而exec是修改当前shell进程全局文件描述符的操作,关闭之后整个shell会话里这个描述符就彻底失效了,后面的echo命令默认要往stdout输出,自然找不到可用的文件描述符,报错也就不奇怪了。

咱们拆解下你的代码逻辑:

  • 走else分支时,你执行exec 1>output.txt把stdout重定向到文件,随后直接用exec 1>&-关闭了fd1;
  • 走then分支时,你关闭了fd2;
    不管走哪个分支,对应的核心文件描述符都会被彻底关掉,后续的echo "Some text"肯定没法正常输出。

那怎么解决呢?给你两种常用的靠谱方案:

方案1:先保存原文件描述符,用完再恢复

核心思路是在重定向之前,把原来的stdout/stderr临时保存到另一个闲置的文件描述符(比如fd3),输出完成后再把原描述符恢复回来,最后关闭临时保存的fd。

修改后的代码示例:

echo "Enter the number between 5 and 10"
read number
if [[ $number -le 5 || $number -ge 10 ]]
then
    echo "There is an error!"
    # 先保存原来的stderr到fd3
    exec 3>&2
    # 重定向stderr到error.txt
    exec 2>error.txt
    echo "---------------------" >&2
    echo "Your answer is $number" >&2
    echo "I wanted you to enter number between 5 and 10!" >&2
    # 恢复stderr到原来的fd2
    exec 2>&3
    # 关闭临时保存的fd3
    exec 3>&-
else
    echo "You are really good!"
    # 先保存原来的stdout到fd3
    exec 3>&1
    # 重定向stdout到output.txt
    exec 1>output.txt
    echo "---------------------"
    echo "You are so cool! Your answer is correct!"
    echo "Your answer was $number"
    # 恢复stdout到原来的fd1
    exec 1>&3
    # 关闭临时保存的fd3
    exec 3>&-
fi
echo "Some text"

方案2:用子shell包裹需要重定向的命令

如果不想折腾文件描述符的保存恢复,更简单的方式是把需要输出到文件的命令放在子shell里(用括号()包裹)。子shell的重定向只会影响子进程,完全不会修改主shell的文件描述符,这样主shell里的stdout/stderr始终是正常可用的。

修改后的代码示例:

echo "Enter the number between 5 and 10"
read number
if [[ $number -le 5 || $number -ge 10 ]]
then
    echo "There is an error!"
    # 子shell里重定向stderr到文件,不影响主shell
    (
        echo "---------------------" >&2
        echo "Your answer is $number" >&2
        echo "I wanted you to enter number between 5 and 10!" >&2
    ) 2>error.txt
else
    echo "You are really good!"
    # 子shell里重定向stdout到文件,不影响主shell
    (
        echo "---------------------"
        echo "You are so cool! Your answer is correct!"
        echo "Your answer was $number"
    ) > output.txt
fi
echo "Some text"

这两种方案都能完美解决你后面echo报错的问题,选哪种看你个人习惯就行~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:27:33