Vérifiez la limite de FD ouverte pour un processus donné dans Linux
j'ai récemment eu un processus Linux qui a" divulgué " des descripteurs de fichiers: il les a ouverts et n'a pas correctement fermé certains d'entre eux.
si j'avais surveillé cela, je pourrais dire - à l'avance - que le processus atteignait sa limite.
y a-t-il une bonne façon, BashPython de vérifier le rapport d'utilisation de FD pour un processus donné dans un système Linux Ubuntu?
EDIT:
je sais maintenant comment vérifier combien de descripteurs de fichiers ouverts y a-t-il; je n'ai besoin de savoir que combien de descripteurs de fichiers sont autorisés pour un processus . Certains systèmes (comme Amazon EC2) n'ont pas le fichier /proc/pid/limits
.
Merci,
Udi
7 réponses
compter les entrées dans /proc/<pid>/fd/
. Les limites dures et douces s'appliquant au procédé se trouvent dans /proc/<pid>/limits
.
les seules interfaces fournies par le noyau Linux pour obtenir des limites de ressources sont getrlimit()
et /proc/
pid /limits
. getrlimit()
ne peut obtenir que les limites de ressources du processus d'appel. /proc/
pid /limits
" vous permet d'obtenir les limites de ressources de tout processus avec le même identifiant utilisateur, et est disponible sur RHEL 5.2, RHEL 4.7, Ubuntu 9.04, et tout distribution avec un noyau 2.6.24 ou plus récent.
si vous avez besoin de prendre en charge des systèmes Linux plus anciens, alors vous devrez obtenir le processus lui-même à appeler getrlimit()
. Bien sûr, la façon la plus simple de le faire est par la modification du programme ou d'une bibliothèque qu'il utilise. Si vous exécutez le programme, vous pourriez utiliser LD_PRELOAD
pour charger votre propre code dans le programme. Si aucun de ceux - ci ne sont possibles, alors vous pouvez attacher au processus avec gdb et lui faire exécuter l'appel dans le processus. Vous pouvez également faire la même chose vous-même en utilisant ptrace()
pour attacher au processus, insérer l'appel dans sa mémoire, etc. cependant c'est très compliqué à obtenir le droit et n'est pas recommandé.
avec les privilèges appropriés, les autres façons de faire cela impliqueraient de regarder à travers la mémoire du noyau, de charger un module du noyau, ou de modifier le noyau, mais je suppose que ceux-ci sont hors de question.
vous pouvez essayer d'écrire un script qui appelle périodiquement lsof -p {PID}
sur un pid donné.
vous avez demandé des méthodes bash/python. ulimit serait la meilleure approche de bash (à moins de passer par /proc/$pid/fd
et ainsi de suite à la main). Pour python, vous pouvez utiliser le module de ressources.
import resource
print(resource.getrlimit(resource.RLIMIT_NOFILE))
$ python test.py (1024, 65536)
resource.getrlimit
correspond à l'appel getrlimit
dans un programme C. Les résultats représentent les valeurs actuelles et maximales de la ressource demandée. Dans l'exemple ci-dessus, le courant (soft) de la limite est de 1024. Les valeurs sont des valeurs par défaut typiques des systèmes Linux de nos jours.
pour voir les 20 premiers fichiers gérer en utilisant des processus:
for x in `ps -eF| awk '{ print }'`;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
la sortie est dans le format de fichier de gérer le nombre, pid, cmndline pour les processus de
exemple de sortie
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
dans CentOS 6 et inférieur (tout ce qui utilise GCC 3), vous pouvez trouver que le réglage des limites du noyau ne résout pas le problème. C'est parce qu'il y a une valeur FD_SETSIZE qui est définie au moment de la compilation utilisé par GCC. Pour cela, vous devrez augmenter la valeur puis recompiler le processus.
en outre, vous pouvez trouver que vous fuyez des descripteurs de fichier en raison de problèmes connus dans libpthread si vous utilisez que bibliothèque. Cet appel a été intégré dans GCC dans GCC 4 / CentOS7 / RHEL 7 et cela semble avoir réglé les problèmes de filetage.
wrapper Python à l'aide de l'excellent psutil paquet:
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