如何通过 Linux shell 命令关闭文件描述符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5987820/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 04:03:48  来源:igfitidea点击:

How to close file descriptor via Linux shell command

linuxshellfile-descriptor

提问by Eric

In /proc/pid/fd/, there are too many file descriptors. Can I use shell command to close these file descriptors?

在 中/proc/pid/fd/,文件描述符太多。我可以使用 shell 命令关闭这些文件描述符吗?

回答by Ignacio Vazquez-Abrams

You can close a FD nof the current process in bash as so:

您可以n在 bash 中关闭当前进程的 FD ,如下所示:

exec n<&-

回答by MarkR

You can't just go around closing other processes' file descriptors and expect them to keep working.

您不能只是绕过关闭其他进程的文件描述符并期望它们继续工作。

Fix the program which has too many files open to make it open fewer. This may be a config change, or modifying the source etc. You can't just close the files for it.

修复打开文件过多的程序,使其打开较少。这可能是配置更改或修改源等。您不能只是关闭它的文件。

回答by Thomas Vander Stichele

You can definitely close fd's of other running processes as long as you have the permissions to do so.

只要您有权限,您绝对可以关闭其他正在运行的进程的 fd。

First, find the PID.

首先,找到PID。

Then, start gdb and attach to the process:

然后,启动 gdb 并附加到进程:

gdb -p 1598

Then, call the close system call on the fd you want to close:

然后,在要关闭的 fd 上调用 close 系统调用:

(gdb) call close(999)
 = 0

If the file descriptor was a leaked one, then the program will never try to use it again anyway, and it shouldn't cause any issues. The program most likely has a bug, however.

如果文件描述符是泄露的,那么程序无论如何都不会再尝试使用它,也不应该引起任何问题。但是,该程序很可能存在错误。

回答by YSC

I've ran in a similar situation, but where gdbwas not an option since it disrupted the real-time constraints of my application and distorted my test.

我在类似的情况下运行过,但哪里gdb不是一个选项,因为它破坏了我的应用程序的实时约束并扭曲了我的测试。

So I came up with a quick iptablesrule. Optional arguments put into square brackets ([ opt ]).

所以我想出了一个快速的iptables规则。置于方括号 ( [ opt ]) 中的可选参数

  1. Find your destination address and port:

    netstat --program [ --numeric-host --numeric-ports ] | grep [<pid>]/[<appname>]

    $ netstat --program --numeric-ports | grep 8812/
    tcp        0      0 ysc.xxx:54055          10.56.1.152:30000           ESTABLISHED 8812/my-application
    tcp        0      0 ysc.xxx:46786          postgres.xxx:5432           ESTABLISHED 8812/my-application
    tcp        0      0 ysc.xxx:36090          10.56.4.79:57000            ESTABLISHED 8812/my-application
                                          ...
    unix  2      [ ]         DGRAM                    7177020 8812/my-application
    

    Here, I'd like to cut 10.56.4.79:57000.

  2. Create an iptablesrule to cut the socket:

    iptables -A OUTPUT [ --out-interface <if> --protocol <tcp|udp|unix> ] --destination <addr> --dport <port> --jump DROP

    $ iptables -A OUTPUT --destination 10.56.4.79 --dport 57000 --jump DROP
    $
    
  3. At this stage, your program can't send packets to the distant host. In most cases, the TCP connection is closed. You can proceed with your tests if there is some.

    $ netstat --program --numeric-ports | grep 8812/
    tcp        0      0 ysc.xxx:54055          10.56.1.152:30000           ESTABLISHED 8812/my-application
    tcp        0      0 ysc.xxx:46786          postgres.xxx:5432           ESTABLISHED 8812/my-application
                                          ...
    unix  2      [ ]         DGRAM                    7177020 8812/my-application
    
  4. Remove the iptablesrule:

    You just type in the same iptablesrule replacing the Aby a D.

    $ iptables -D OUTPUT --destination 10.56.4.79 --dport 57000 --jump DROP
    $
    
  1. 找到您的目的地地址和端口

    netstat --program [ --numeric-host --numeric-ports ] | grep [<pid>]/[<appname>]

    $ netstat --program --numeric-ports | grep 8812/
    tcp        0      0 ysc.xxx:54055          10.56.1.152:30000           ESTABLISHED 8812/my-application
    tcp        0      0 ysc.xxx:46786          postgres.xxx:5432           ESTABLISHED 8812/my-application
    tcp        0      0 ysc.xxx:36090          10.56.4.79:57000            ESTABLISHED 8812/my-application
                                          ...
    unix  2      [ ]         DGRAM                    7177020 8812/my-application
    

    在这里,我想削减10.56.4.79:57000

  2. 创建一个iptables规则来切割套接字

    iptables -A OUTPUT [ --out-interface <if> --protocol <tcp|udp|unix> ] --destination <addr> --dport <port> --jump DROP

    $ iptables -A OUTPUT --destination 10.56.4.79 --dport 57000 --jump DROP
    $
    
  3. 在此阶段,您的程序无法向远程主机发送数据包。在大多数情况下,TCP 连接是关闭的。如果有的话,您可以继续进行测试。

    $ netstat --program --numeric-ports | grep 8812/
    tcp        0      0 ysc.xxx:54055          10.56.1.152:30000           ESTABLISHED 8812/my-application
    tcp        0      0 ysc.xxx:46786          postgres.xxx:5432           ESTABLISHED 8812/my-application
                                          ...
    unix  2      [ ]         DGRAM                    7177020 8812/my-application
    
  4. 删除iptables规则

    您只需输入相同的iptables规则,A用 a替换D

    $ iptables -D OUTPUT --destination 10.56.4.79 --dport 57000 --jump DROP
    $
    

回答by ks1322

@Thomas answer is valid only when debug information for close()call is installed.

@Thomas 回答仅在close()安装了呼叫的调试信息时才有效。

Without debug info installed, gdb refuses to call close():

没有安装调试信息,gdb 拒绝调用close()

(gdb) call close(3)
'close' has unknown return type; cast the call to its declared return type

The simplest way to make gdb call close()in this case is to cast the call to close()return type:

close()在这种情况下进行 gdb 调用的最简单方法是将调用转换为close()返回类型:

(gdb) call (int)close(3)
 = 0

See gdb documentation:

请参阅 gdb文档

Sometimes, a function you wish to call is missing debug information. In such case, GDB does not know the type of the function, including the types of the function's parameters. To avoid calling the inferior function incorrectly, which could result in the called function functioning erroneously and even crash, GDB refuses to call the function unless you tell it the type of the function.

For prototyped (i.e. ANSI/ISO style) functions, there are two ways to do that. The simplest is to cast the call to the function's declared return type.

有时,您希望调用的函数缺少调试信息。在这种情况下,GDB 不知道函数的类型,包括函数参数的类型。为了避免错误调用劣势函数,导致被调用函数运行错误甚至崩溃,GDB 拒绝调用该函数,除非你告诉它函数的类型。

对于原型(即 ANSI/ISO 风格)函数,有两种方法可以做到这一点。最简单的方法是将调用转换为函数声明的返回类型。