关闭bash中的所有文件描述符


13

有没有办法关闭所有打开的文件描述符,而无需事先获得它们的明确列表?


4
所有哪些文件描述符?每个过程都有一些开放性。
沃伦·杨

什么是“所有打开的文件描述符”?0、1和2?还是您还有更多?如果是这样,它们来自哪里?
U. Windl

脚本完成后,文件描述符不是自动关闭吗?
jarno

Answers:


15

要从字面上回答,请关闭以下所有打开的文件描述符bash

for fd in $(ls /proc/$$/fd); do
  eval "exec $fd>&-"
done

但是,这实际上不是一个好主意,因为它将关闭外壳程序用于输入和输出所需的基本文件描述符。如果执行此操作,则您运行的所有程序都不会在终端上显示其输出(除非它们tty直接写入设备)。如果在我的测试中,事实关闭stdinexec 0>&-)只会导致交互式外壳退出。

您实际上可能希望做的是关闭不属于shell基本操作一部分的所有文件描述符。这些是0代表stdin,1代表stdout和2代表stderr。最重要的是,一些shell似乎默认还打开了其他文件描述符。在bash,例如,你有255(也可用于终端I / O),并在dash我有10个,这点/dev/tty而不是具体tty/ pts装置的终端使用。要关闭除0、1、2和255外的所有内容,请执行以下操作bash

for fd in $(ls /proc/$$/fd); do
  case "$fd" in
    0|1|2|255)
      ;;
    *)
      eval "exec $fd>&-"
      ;;
  esac
done

还请注意,eval重定向变量中包含的文件描述符时,这是必需的,如果不bash进行扩展,则将变量视为命令的一部分(在这种情况下,它将尝试访问exec命令01尝试关闭的文件描述符)。

注意:同样使用glob代替ls(例如/proc/$$/fd/*)似乎会为glob打开一个额外的文件描述符,因此ls似乎是最好的解决方案。

更新资料

有关的可移植性的更多信息/proc/$$/fd,请参见文件描述符链接的可移植性。如果/proc/$$/fd不可用,则使用替换掉的$(ls /proc/$$/fd)使用lsof(如果可用)将是$(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-)


/proc仅在Linux下可用。
chepner 2014年

4
@chepner,如果您说那/proc/PID/fd不是很轻便的话,那将是对的。但是说这/proc仅在Linux下可用并不是正确的说法。
Graeme 2014年

一些网站使用该<&-表格,是否有所不同/需要?
Lorenzo Pistone 2014年

@LorenzoPistone,关闭描述符时方向不变,因此可以使用任何一种形式。
Graeme 2014年

5

在Bash的最新版本(4.1及更高版本,2009年及更高版本)中,您可以使用shell变量指定要关闭的文件描述符:

for fd in $(ls /proc/$$/fd/); do
    [ $fd -gt 2 ] && exec {fd}<&-
done

该功能早在1993年就已经存在于Korn shell中,但显然花了一些时间才进入Bash。


1

清除除当前shell的I / O / E之外的所有文件描述符,但不包括作为参数提供的文件描述符

clear_fds() {
for fd in $(compgen -G "/proc/$BASHPID/fd/*"); do
    fd=${fd/*\/}
        if [[ ! " $* " =~ " ${fd} " ]]; then
            case "$fd" in
                0|1|2|255)
                ;;
                *)
                    eval "exec $fd>&-"
                    ;;
            esac
        fi
done
}

0

完全没有“ eval”的另一种方法是使用以下形式:

$ exec {var_a}>> file.txt
$ echo $var_a
10
$ ls -l /proc/self/fd/10
l-wx------ 1 0 0 64 Dec 11 18:32 /proc/self/fd/10 -> /run/user/0/tmp/file.txt
$ echo "aaaaa" >&$var_a
$ cat file.txt
aaaaa
$ exec {var_a}>&-
$ ls /proc/self/fd/10
ls: cannot access '/proc/self/fd/10': No such file or directory

但这并不能关闭所有文件描述符。
G-Man说'Resstate Monica''De​​c

确实。您必须像前面的答复中所解释的那样执行一个循环...只是要指出一个事实,在这里“ eval”不是强制性的,我们可以使用相同的逻辑来关闭它而不是打开它。手册页上确实对此并不清楚...
David DG

0

不能。内核一次只能关闭一个FD,而bash没有FD的“组命令”。

for fd in $(ls -1 /proc/27343/fd); do echo exec $fd">&"-; done

删除echo"之后的测试。

如果这不是用于shell本身,而是用于运行命令,则可以使用nohup


2
所使用的文件描述符>&-不能是参数;重定向是在参数扩展之前解析的。
chepner 2014年

1
如今,@ chepner exec {fd}>&-可以工作。
jarno
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.