Comment grep netcat sortie

J'essaie de grep stream de text en direct de netcat , mais cela ne fonctionne pas pour moi:

 netcat localhost 9090 | grep sender 

ne returnne rien, mais je suis sûr que ça devrait le faire.

Si je redirige la sortie netcat vers un file et ajoute quelques retards (simuler un environnement réel) – alors ça marche:

 $ (sleep 5; cat netcat_output; sleep 5) | grep sender {"jsonrpc":"2.0","method":"GUI.OnScreensaverDeactivated","params":{"data": "shuttingdown":false},"sender":"xbmc"}} 

J'ai aussi essayé d'append --line-buffered mais sans succès.

Qu'est-ce que je fais mal?

Modifier:

J'ai remarqué le même problème avec sed , la sortie est vide.

Mais, par exemple, hexdump convertit le text en hexadécimal:

 $ netcat localhost 9090 | hexdump -C 00000000 7b 22 6a 73 6f 6e 72 70 63 22 3a 22 32 2e 30 22 |{"jsonrpc":"2.0"| 00000010 2c 22 6d 65 74 68 6f 64 22 3a 22 50 6c 61 79 65 |,"method":"Playe| 00000020 72 2e 4f 6e 50 6c 61 79 22 2c 22 70 61 72 61 6d |r.OnPlay","param| 00000030 73 22 3a 7b 22 64 61 74 61 22 3a 7b 22 69 74 65 |s":{"data":{"ite| 00000040 6d 22 3a 7b 22 69 64 22 3a 36 2c 22 74 79 70 65 |m":{"id":6,"type| 00000050 22 3a 22 6d 6f 76 69 65 22 7d 2c 22 70 6c 61 79 |":"movie"},"play| 00000060 65 72 22 3a 7b 22 70 6c 61 79 65 72 69 64 22 3a |er":{"playerid":| 00000070 31 2c 22 73 70 65 65 64 22 3a 31 7d 7d 2c 22 73 |1,"speed":1}},"s| 

Vous pouvez utiliser la command read ( bash builtin) pour forcer la lecture des caractères un par un:

 netcat localhost 9090 | ( cnt=0 line= while read -N 1 c; do line="$line$c" if [ "$c" = "{" ]; then cnt=$((cnt+1)) elif [ "$c" = "}" ]; then cnt=$((cnt-1)) if [ $cnt -eq 0 ]; then printf "%s\n" "$line" line= fi fi done ) | grep sender 

Ce script doit imprimer chaque sortie complète avec { et } équilibrage, mais vous pouvez modifier le script pour qu'il fasse ce que vous voulez. Ce script ne ferait pas bien sur un benchmark par rapport à presque tout, mais c'est assez simple et semble fonctionner pour moi …

Notez que votre échantillon de test n'a pas été assorti { et } , donc si c'est le cas de l'input réelle, vous pouvez modifier les critères pour imprimer la ligne.

Je pense que la question est l'absence de nouvelles lignes dans la sortie netcat . Je peux voir deux solutions de contournement:

  1. Insérer une nouvelle ligne toutes les x secondes (avec des conséquences malheureuses si la nouvelle ligne est insérée au milieu de la source ):

     ( while sleep 1; do echo; done & netcat ... ) | grep source 
  2. Utilisez awk avec un RS autre que newline:

     netcat ... | awk -v RS='}' -v ORS='}' '/source/' 

La réponse est ici: grep ne correspond pas dans la sortie nc

netcat sort des journaux verbeux en erreur standard, donc nous devons capturer les erreurs avant de nous diriger vers grep.

 $ netcat -zv localhost 1-9000 2>&1 | grep succeeded 

Ajouter – --line-buffered pour utiliser la mise en tampon de ligne sur la sortie:

 netcat localhost 9090 | grep --line-buffered sender 

utiliser la command de watch :

 watch 'netcat localhost 9090 | grep sender' 

Selon le commentaire @ user43791 , essayez de désactiver la mise en memory tampon dans le canal , par exemple:

 stdbuf -o0 netcat localhost 9090 | grep sender 

Dans Bash, vous pouvez utiliser des files de pseudo-périphérique pour ouvrir une connection TCP et la grep comme d'habitude. Par exemple:

 $ grep "sender" < /dev/tcp/example.com/1234 

Pour le tester, il suffit d'exécuter le server qui peut envoyer un file, comme:

 $ nc -vl 1234 < /etc/hosts 

Ensuite, dans un autre terminal, exécutez le test pour grep la sortie:

 $ grep "127" < /dev/tcp/localhost/1234 127.0.0.1 localhost