在/proc/pid/fd/
中,文件描述符太多。我可以使用shell命令关闭这些文件描述符吗?
答案 0 :(得分:32)
只要您有权执行此操作,就可以关闭其他正在运行的进程的fd。
首先,找到PID。
然后,启动gdb并附加到进程:
gdb -p 1598
然后,在您要关闭的fd上调用close系统调用:
(gdb) call close(999)
$1 = 0
如果文件描述符是泄露的,那么程序永远不会尝试再次使用它,它不会导致任何问题。但是,该程序最有可能存在错误。
答案 1 :(得分:5)
您可以在bash中关闭当前进程的FD n
,如下所示:
exec n<&-
答案 2 :(得分:2)
我遇到了类似的情况,但gdb
不是一个选项,因为它破坏了我的应用程序的实时约束并扭曲了我的测试。
所以我提出了一个快速的iptables
规则。 可选参数放在方括号([ opt ]
)。
查找目的地址和端口:
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
。
创建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
$
在此阶段,您的程序无法将数据包发送到远程主机。在大多数情况下, 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
删除iptables
规则:
您只需输入相同的iptables
规则,将A
替换为D
。
$ iptables -D OUTPUT --destination 10.56.4.79 --dport 57000 --jump DROP
$
答案 3 :(得分:0)
@Thomas答案仅在安装了close()
呼叫的调试信息时才有效。
未安装调试信息,gdb拒绝调用close()
:
(gdb) call close(3)
'close' has unknown return type; cast the call to its declared return type
在这种情况下,使gdb调用close()
的最简单方法是将调用转换为close()
返回类型:
(gdb) call (int)close(3)
$1 = 0
请参见gdb documentation:
有时,您要调用的函数缺少调试信息。 在这种情况下,GDB不知道函数的类型,包括 函数参数的类型。避免叫劣等 功能不正确,可能导致调用函数 错误地运行甚至崩溃,GDB拒绝调用 函数,除非您告诉它函数的类型。
对于原型函数(即ANSI / ISO样式),有两种方法 去做。最简单的方法是将调用强制转换为该函数的已声明 返回类型。
答案 4 :(得分:-1)
你不能只是绕过关闭其他进程的文件描述符并期望它们继续工作。
修复打开了太多文件的程序,使其打开的次数减少。这可能是配置更改,或修改源等。您不能只关闭它的文件。