Introduction à quelques outils du Shell : lsof, ngrep et netstat

Dans ce post, nous allons découvrir 3 outils du Shell qui permettent de debugger des applications, et pas uniquement des applications Java.

Cas d’usage

Chez un client, nous mettons en place la stack ELK (Elasticsearch, Logstash, Kibana) pour centraliser les logs d’applications et les rendre disponibles via l’interface Web de Kibana. Nous utilisons également Beaver pour effectuer l’acheminement des logs (log shipping), Beaver étant beaucoup plus léger que Logstash.

Détail des briques logicielles que nous utilisons et leur relations :

  • Beaver : monitore des fichiers de logs et envoie les nouvelles lignes à Logstash (en TCP).
  • Logstash : reçoit des logs en TCP (port 53021), les parse, et envoie les logs parsés à Elasticsearch (en HTTP)
  • Elasticsearch : reçoit des requêtes d’indexation en HTTP (port 9200) et stocke les logs.
  • Kibana : permet de visualiser les logs stockés dans Elasticsearch.

Lors de la mise en place de cette stack, à chaque fois qu’une application écrit une nouvelle ligne de log dans un fichier, cette ligne doit être acheminée, parsée, indexée et stockée, pour finalement être visualisée dans Kibana. Si la ligne n’apparait pas, la cause peut être multiple :

  • Le fichier de log était-il monitoré par Beaver ?
  • Beaver a-t-il transmis le log à Logstash ?
  • Logstash a-t-il transmis le log à Elasticsearch ?

Autant de questions auxquelles lsof, ngrep et netstat peuvent nous permettre de répondre.

lsof

lsof permet de lister les fichiers ouverts par une application (“list open files”). On peut donc vérifier que Beaver est en train de monitorer les fichiers de logs de nos applications :

lsof

Une particularité intéressante d’Unix est qu’une connexion réseau est un fichier. On peut donc vérifier que Beaver a une connexion ouverte vers Logstash :

lsof-reseau

Notons que l’option -P permet d’indiquer qu’on ne souhaite pas convertir les numéros de port en noms de port (ex : convertir “80” en “HTTP”) ce qui est pratique si on veut grep’er un numéro de port.

ngrep

Jusqu’ici, Beaver semble lire les fichiers et envoyer les logs à Logstash. Grâce à ngrep (“network grep“) nous pouvons vérifier que les données transitent effectivement jusqu’à Logstash :

ngrep-beaver

Détaillons la ligne de commande :

ngrep -d lo -W byline -t -q '' 'dst port 53021'
      |     |         |  |  |  |
      |     |         |  |  |  +> expression de filtre (ici, tout ce qui est à destination
      |     |         |  |  |     du port 53021)
      |     |         |  |  |
      |     |         |  |  +---> expression de match (porte sur le contenu des paquets)
      |     |         |  |
      |     |         |  +------> quiet : ne rien afficher d'autre que les paquets
      |     |         |
      |     |         +---------> afficher un timestamp à chaque réception de paquet
      |     |  
      |     +-------------------> mode d'affichage ("byline" est surtout pratique pour du HTTP)
      |
      +-------------------------> interface à écouter : localhost, dans notre cas

Il faudra adapter les paramètres au contenu que l’on souhaite capturer. Par exemple, l’expression de match '^(GET|POST) ' permettra de ne récupérer que les requêtes GET ou POST d’un flux HTTP.

Attention à bien spécifier une expression de match vide (”) si on ne veut pas filtrer sur le contenu des paquets, faute de quoi l’expression de filtre serait interprétée comme une expression de match.

netstat

Avec lsof, nous avons pu vérifier qu’une connexion TCP était établie entre deux points. Hors, si une connexion n’est pas établie, il faut vérifier si le serveur est bien à l’écoute. netstat permet cela :

netstat

Ici, nous avons grep’é le PID du processus Elasticsearch pour restreindre les résultats. On voit directement qu’Elasticsearch écoute sur les ports 9200 et 9300.

Les options que nous avons utilisées :

netstat -ptnl |||| ||||+> affiche les sockets en écoute ||| |||+> ne pas convertir les adresses et numéros de port en noms || ||+> affiche uniquement les sockets TCP | |+> afficher le PID et le nom du processus

En remplaçant l’option -l par -a, on peut afficher toutes les connexions réseau :

netstat-all

Conclusion

Les outils lsofngrep et netstat nous fournissent des informations sur les processus, qu’ils soient Java ou non. Ils permettent ainsi d’observer les interactions des processus avec le système et ce, de manière fiable, sans avoir à faire confiance à des indications lues dans un fichier de log. Des informations qui sont donc précieuses pour le debugging.