最近、ファイル記述子を「漏出」させるLinuxプロセスがありました。ファイル記述子を開き、それらの一部を適切に閉じませんでした。
これを監視していた場合、プロセスが限界に達していることを事前に知ることができました。
Ubuntu Linuxシステムで特定のプロセスのFD使用率を確認するニース、Bash\Pythonの方法はありますか?
編集:
開いているファイル記述子の数を確認する方法がわかりました。 プロセスに許可されるファイル記述子の数を知る必要があるだけです。一部のシステム(Amazon EC2など)には/proc/pid/limits
ファイル。
おかげで、
ウディ
/proc/<pid>/fd/
のエントリをカウントします。プロセスに適用されるハード制限とソフト制限は、/proc/<pid>/limits
にあります。
リソース制限を取得するためにLinuxカーネルが提供する唯一のインターフェースは、 getrlimit()
と _/proc/
_pid_/limits
_ 。 getrlimit()
は、呼び出しプロセスのリソース制限のみを取得できます。 _/proc/
_pid_/limits
_を使用すると、同じユーザーIDを持つプロセスのリソース制限を取得でき、RHELで利用できます5.2、RHEL 4.7、Ubuntu 9.04、および2.6.24以降のカーネルを備えたディストリビューション。
古いLinuxシステムをサポートする必要がある場合は、getrlimit()
を呼び出すプロセス自体を取得する必要があります。もちろん、それを行う最も簡単な方法は、プログラムまたはそれが使用するライブラリを変更することです。プログラムを実行している場合は、_LD_PRELOAD
_を使用して独自のコードをプログラムにロードできます。これらのいずれも使用できない場合は、gdbを使用してプロセスにアタッチし、プロセス内で呼び出しを実行させることができます。 ptrace()
を使用してプロセスにアタッチしたり、メモリに呼び出しを挿入するなどして、同じことを自分で行うこともできますが、これは非常に複雑で適切ではありません。
適切な特権があれば、これを行う他の方法には、カーネルメモリの確認、カーネルモジュールのロード、またはカーネルの変更が含まれますが、これらは問題外であると想定しています。
プロセスを使用して上位20のファイルハンドルを表示するには:
for x in `ps -eF| awk '{ print $2 }'`;do echo `ls /proc/$x/fd 2> /dev/null | wc -l` $x `cat /proc/$x/cmdline 2> /dev/null`;done | sort -n -r | head -n 20
出力は、プロセスのファイルハンドルカウント、pid、cmndlineの形式です。
出力例
701 1216 /sbin/rsyslogd-n-c5
169 11835 postgres: spaceuser spaceschema [local] idle
164 13621 postgres: spaceuser spaceschema [local] idle
161 13622 postgres: spaceuser spaceschema [local] idle
161 13618 postgres: spaceuser spaceschema [local] idle
Bash/pythonメソッドを要求しました。 ulimitは最良のbashアプローチです(/proc/$pid/fd
など。 Pythonの場合、リソースモジュールを使用できます。
import resource
print(resource.getrlimit(resource.RLIMIT_NOFILE))
$ python test.py (1024, 65536)
resource.getrlimit
は、Cプログラムのgetrlimit
呼び出しに対応します。結果は、要求されたリソースの現在の値と最大値を表します。上記の例では、現在の(ソフト)制限は1024です。最近の値は、Linuxシステムの典型的なデフォルトです。
特定のpidでlsof -p {PID}
を定期的に呼び出すスクリプトを作成してみてください。
優れたpsutilパッケージを使用したPythonラッパー:
import psutil
for p in psutil.process_iter(attrs=['pid', 'name', 'username', 'num_fds']):
try:
soft, hard = p.rlimit(psutil.RLIMIT_NOFILE)
cur = p.info['num_fds']
usage = int(cur / soft * 100)
print('{:>2d}% {}/{}/{}'.format(
usage,
p.info['pid'],
p.info['username'],
p.info['name'],
))
except psutil.NoSuchProcess:
pass
CentOS 6以前(GCC 3を使用するもの)では、カーネルの制限を調整しても問題が解決しない場合があります。これは、GCCが使用するコンパイル時に設定される FD_SETSIZE 値があるためです。そのためには、値を増やしてからプロセスを再コンパイルする必要があります。
また、そのライブラリを使用している場合、 libpthreadの既知の問題 が原因でファイル記述子がリークしていることがあります。この呼び出しはGCC 4/CentOS7/RHEL 7のGCCに統合され、これによりスレッドの問題が修正されたようです。