20 votes

Sockets trouvés par lsof mais pas par netstat

J'ai une application qui manque de descripteurs de fichiers, apparemment en ouvrant des sockets, mais je n'arrive pas à savoir ce que font exactement ces sockets. Ils apparaissent dans la sortie lsof comme

java    9689 appuser 1010u  sock       0,5          263746675 can't identify protocol
java    9689 appuser 1011u  sock       0,5          263746676 can't identify protocol
java    9689 appuser 1012u  sock       0,5          263746677 can't identify protocol
java    9689 appuser 1014u  sock       0,5          263746678 can't identify protocol
java    9689 appuser 1015u  sock       0,5          263746679 can't identify protocol
java    9689 appuser 1016u  sock       0,5          263746681 can't identify protocol

et dans /proc/$PID/fd en tant que

lrwx------ 1 appuser appuser 64 Jun 23 11:49 990 -> socket:[263732085]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 991 -> socket:[263732086]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 992 -> socket:[263735307]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 993 -> socket:[263732088]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 995 -> socket:[263735308]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 996 -> socket:[263735309]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 997 -> socket:[263745434]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 998 -> socket:[263745435]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 999 -> socket:[263745436]

mais il n'y a pas de sortie similaire dans netstat -a .

Que sont ces prises et comment puis-je savoir ce qu'elles font ?

Modifier : J'ai essayé d'exécuter grep $SOCKET /proc/net comme recommandé dans le lsof FAQ où $SOCKET est par exemple 263746679, mais cela n'a pas donné de résultats non plus.


En arrière-plan, l'application est un conteneur pour de multiples tâches qui, entre autres, effectuent des appels réseau. J'ai besoin d'isoler celle qui devient folle, mais jusqu'à ce que je trouve avec qui ces sockets communiquent, je suis coincé.

17voto

BMDan Points 7059

Cela peut se produire si vous créez une socket, mais que vous n'avez jamais connecté() ou bind() avec elle. Votre meilleure chance est de stracer (-fF) l'application, puis de croiser les résultats de lsof pour déterminer quelles sont les sockets qui posent problème. Une méthode de débogage supplémentaire : si vous enveloppez vos appels de socket avec des informations de débogage et que vous les écrivez dans /dev/null, elles apparaîtront dans strace sans vous donner des fichiers journaux hilarants.

3voto

Mongo Points 11

En utilisant Python, j'ai rencontré le même problème sur les sockets SSL :

  • Lorsque j'utilise socket.close(), la socket reste dans l'état CLOSE_WAIT pendant une durée indéterminée.
  • quand j'utilise socket.shutdown(), lsof dit "ne peut pas identifier le protocole".

La solution consistait à déballer la couche SSL avant la fermeture :

  • origsock = socket.unwrap()
  • origsock.close()

Cela ferme les sockets correctement dans mon application.

2voto

Georg Points 58

La première chose que je ferais est d'augmenter la limite de votre descripteur de fichier :

~# vi /etc/sysctl.conf
fs.file-max = 331287

Ensuite, je m'assurerais que votre système est à jour, ce qui inclut toutes les bibliothèques et les serveurs. Il est possible que votre serveur d'application Java ne soit pas à jour (si vous en utilisez un). Il est également possible que votre serveur d'application soit mal configuré, vous devriez regarder votre fichier de configuration et abaisser le niveau de votre connectionTimeout et/ou votre maxKeepAliveRequests (Je ne suis pas sûr du serveur d'application que vous utilisez ou si vous en utilisez un du tout...).

Je ne suis pas sûr de ce que fait cette application, mais si vous ne pensez pas qu'elle nécessite des dizaines de milliers de sockets, alors il s'agit presque certainement d'un problème de sécurité. "fuite de descripteur de fichier" dans votre application Java. Vous devrez peut-être envoyer un rapport de bogue au fournisseur. Dans ce rapport de bogue, vous devez inclure des informations sur la façon de recréer le problème.

Voici quelques moyens de déboguer le problème.

Wireshark (ou twireshark pour le cli) est le meilleur outil pour voir comment ces sockets sont utilisés. Wireshark vous donnera une décomposition du type de trafic envoyé sur le câble. Il est probable que les premières connexions aboutissent, puis qu'elles atteignent la limite des descripteurs de fichiers. Une fois que la limite du descripteur de fichier est atteinte, Wireshark ne détectera plus rien (et netstat est plus efficace à cet égard), mais cela aidera à circonscrire le problème. Il peut y avoir des cas où beaucoup de SYN sortants sont envoyés, mais où aucun SYN/ACK n'est reçu, ce qui fait que beaucoup de connexions tcp sont bloquées dans l'état SYN_WAIT.

Si vous avez accès au code source et que vous connaissez le type de sockets créés (comme en utilisant strace ou simplement en cherchant dans le code), alors vous pouvez ouvrir le projet dans Eclipse (ou un autre IDE) et définir un point d'arrêt au niveau de la fonction qui crée ces sockets. Lorsque le breakpoint est atteint, vous pouvez alors regarder la trace de la pile. Cette fuite de descripteur de fichier peut être une simple boucle infinie ou peut-être que la valeur du délai d'attente de la socket est trop grande. Une autre possibilité est que l'application java n'effectue pas un socket.close() pour nettoyer les connexions. La fermeture est généralement effectuée dans le cadre d'un processus d'évaluation de l'efficacité du système. finely d'un bloc de try/catch (Oui, un socket doit toujours avoir un try/catch en Java ou il ne sera pas construit :). En fin de compte, il est probable que l'application Java ne gère pas correctement ses exceptions IOException.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X