В /proc/pid/fd/
слишком много файловых дескрипторов. Могу ли я использовать команду оболочки, чтобы закрыть эти файловые дескрипторы?
Как закрыть дескриптор файла с помощью команды оболочки Linux
Ответы (5)
Вы определенно можете закрыть fd других запущенных процессов, если у вас есть на это права.
Сначала найдите PID.
Затем запустите gdb и присоединитесь к процессу:
gdb -p 1598
Затем вызовите системный вызов close для файла fd, который вы хотите закрыть:
(gdb) call close(999)
$1 = 0
Если файловый дескриптор был утекшим, то программа все равно никогда не попытается использовать его снова, и это не должно вызывать никаких проблем. Однако, скорее всего, в программе есть ошибка.
Вы можете закрыть FD n
текущего процесса в bash следующим образом:
exec n<&-
Я работал в похожей ситуации, но где 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 $
Ответ @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 документацию:
Иногда в функции, которую вы хотите вызвать, отсутствует отладочная информация. В таком случае GDB не знает тип функции, включая типы параметров функции. Чтобы избежать неправильного вызова подчиненной функции, что может привести к неправильному функционированию вызываемой функции и даже к сбою, GDB отказывается вызывать функцию, пока вы не сообщите ему тип функции.
Для прототипированных (т. е. в стиле ANSI/ISO) функций есть два способа сделать это. Самый простой — привести вызов к объявленному возвращаемому типу функции.
Вы не можете просто закрыть файловые дескрипторы других процессов и ожидать, что они продолжат работать.
Исправьте программу, в которой открыто слишком много файлов, чтобы она открывалась меньше. Это может быть изменение конфигурации или изменение источника и т. д. Вы не можете просто закрыть файлы для этого.