/proc/pid/fd/
、ファイル記述子が多すぎます。 Shellコマンドを使用してこれらのファイル記述子を閉じることはできますか?
実行中の他のプロセスのfdは、そうする権限がある限り、確実に閉じることができます。
まず、PIDを見つけます。
次に、gdbを起動し、プロセスにアタッチします。
gdb -p 1598
次に、閉じたいfdでcloseシステムコールを呼び出します。
(gdb) call close(999)
$1 = 0
ファイル記述子がリークされた場合、プログラムはとにかくそれを再び使用しようとはせず、問題を引き起こすことはありません。ただし、プログラムにはバグがある可能性があります。
次のように、bashで現在のプロセスのFD n
を閉じることができます。
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スタイル)の関数の場合、これを行うには2つの方法があります。最も簡単なのは、関数の宣言された戻り値の型に呼び出しをキャストすることです。