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
相关产品推荐
相关产品推荐

