Comment grep sortie netcat

13

J'essaie de récupérer le flux de texte en direct à partir de netcat, mais cela ne fonctionne pas pour moi:

netcat localhost 9090 | grep sender

ne renvoie rien, mais je suis sûr que cela devrait.

Si je redirige la netcatsortie vers un fichier et ajoute quelques retards (simuler l'environnement réel) - alors cela fonctionne:

$ (sleep 5; cat netcat_output; sleep 5) | grep sender

{"jsonrpc":"2.0","method":"GUI.OnScreensaverDeactivated","params":{"data": "shuttingdown":false},"sender":"xbmc"}}

J'ai également essayé d'ajouter --line-bufferedmais sans succès.

Ce que je fais mal?

Éditer:

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

Mais, par exemple, hexdumpconvertit le texte en hexadécimal en direct:

$ 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|
tomekceszke
la source
2
Peut-être qu'il est tamponné dans le tuyau? Vous pouvez essayer d'utiliser stdbuf -o0 netcat localhost 9090 | grep sender(extrait d' ici )
user43791
Ça marche comme ça? netcat -z localhost 9090 | grep sender
Gilles Quenot
@ user43791 la sortie est toujours vide, mais je suis sûr que netcat a renvoyé la chaîne correspondante
tomekceszke
@sputnick celui-ci retourne immédiatement au shell et n'attend pas d'événement
tomekceszke
1
Il n'y a pas de nouvelles lignes dans l'hexdump, donc grepattend probablement sans fin une nouvelle ligne. catfonctionne depuis grepobtiendra un EOF sinon une nouvelle ligne, au moins. Peut-être essayer awkavec {RS?
muru

Réponses:

4

Vous pouvez utiliser la readcommande ( bashintégrée) 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 équilibrage {et }, mais vous pouvez modifier le script pour faire ce que vous voulez. Ce script ne ferait PAS bien sur un benchmark par rapport à à peu près n'importe quoi, mais il est assez simple et semble fonctionner pour moi ...

Notez que votre échantillon de test n'a pas de correspondance {et }, donc si c'est le cas de l'entrée réelle, vous souhaiterez peut-être modifier les critères pour imprimer la ligne.

user43791
la source
On dirait que les accolades incompatibles sont simplement parce qu'il n'a publié que le début de la sortie.
Barmar
8

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

netcat génère des journaux détaillés sur erreur standard, nous devons donc capturer les erreurs avant de diriger vers grep.

$ netcat -zv localhost 1-9000 2>&1 | grep succeeded
tkdave
la source
Cette réponse vient de me faire solution. C'était très étrange lorsque j'exécute cette commande sans 2>&1, il semble que grep ne fonctionne pas du tout.
Marecky
2

Je pense que le problème est l'absence de nouvelles lignes dans la netcatsortie. Je peux voir deux solutions:

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

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

    netcat ... | awk -v RS='}' -v ORS='}' '/source/'
    
muru
la source
Sortie encore vide. Pour m'assurer que cette commande est correcte, je cours sur un flux vidé - cat netcat_output | awk -v RS='}' -v ORS='}' '/sender/'La sortie était correcte:,"sender":"xbmc"}
tomekceszke
Je viens de vérifier la première solution de contournement et cela fonctionne ! Mais comme vous l'avez mentionné, il peut diviser la sortie et ne peut donc pas être la solution finale. Quoi qu'il en soit, merci beaucoup!
tomekceszke
1

Ajouter --line-bufferedpour utiliser la mise en mémoire tampon de ligne sur la sortie:

netcat localhost 9090 | grep --line-buffered sender 
Cyrus
la source
J'ai déjà essayé ça, ça n'a pas marché.
tomekceszke
1

utilisez la watchcommande:

watch 'netcat localhost 9090 | grep sender'
αғsнιη
la source
Ça ne marche pas trop. La même chose avec sed ... Mais, par exemple, ceci: netcat localhost 9090 | hexdump fonctionne et remplace le texte par hex live, pourquoi?
tomekceszke
0

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

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

Pour le tester, lancez simplement le serveur qui peut envoyer des fichiers, comme:

$ nc -vl 1234 < /etc/hosts

Ensuite, dans un autre terminal, exécutez le test sur grepla sortie:

$ grep "127" < /dev/tcp/localhost/1234
127.0.0.1   localhost
Kenorb
la source