私は、ファイルを大量に消費する一種のテストスイートを作成しました。しばらくすると(2時間)、IOError: [Errno 24] Too many open files: '/tmp/tmpxsqYPm'
が表示されます。すべてのファイルハンドルを再度閉じるかどうかを再確認しました。しかし、エラーはまだ存在します。
resource.RLIMIT_NOFILE
を使用して、許可されているファイル記述子の数と現在開いているファイル記述子の数を把握しようとしました。
def get_open_fds():
fds = []
for fd in range(3,resource.RLIMIT_NOFILE):
try:
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
except IOError:
continue
fds.append(fd)
return fds
したがって、次のテストを実行すると、次のようになります。
print get_open_fds()
for i in range(0,100):
f = open("/tmp/test_%i" % i, "w")
f.write("test")
print get_open_fds()
私はこの出力を取得します:
[]
/tmp/test_0
[3]
/tmp/test_1
[4]
/tmp/test_2
[3]
/tmp/test_3
[4]
/tmp/test_4
[3]
/tmp/test_5
[4] ...
奇妙なことに、開くファイル記述子の数が増えると予想していました。私のスクリプトは正しいですか?
私はPythonのロガーとサブプロセスを使用しています。それが私のfdリークの理由でしょうか?
ありがとう、ダニエル
テストスクリプトは反復ごとにf
を上書きします。これは、ファイルが毎回閉じられることを意味します。ファイルへのログ記録とパイプを使用したsubprocess
の両方で記述子が使い果たされ、枯渇につながる可能性があります。
修正されたコードは次のとおりです。
import resource
import fcntl
import os
def get_open_fds():
fds = []
soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
for fd in range(0, soft):
try:
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
except IOError:
continue
fds.append(fd)
return fds
def get_file_names_from_file_number(fds):
names = []
for fd in fds:
names.append(os.readlink('/proc/self/fd/%d' % fd))
return names
fds = get_open_fds()
print get_file_names_from_file_number(fds)
resource.RLIMIT_NOFILEは確かに7ですが、これはresource.getrlimit()へのインデックスであり、制限自体ではありません... resource.getrlimit(resource.RLIMIT_NOFILE)は、トップrange()にしたいものです。