Jak grepować wyjście netcat

13

Próbuję grepować strumień tekstu na żywo netcat, ale to nie działa dla mnie:

netcat localhost 9090 | grep sender

nic nie zwraca, ale jestem pewien, że powinien.

Jeśli przekieruję dane netcatwyjściowe do pliku i dodam pewne opóźnienia (symuluję rzeczywiste środowisko) - wtedy działa:

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

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

Próbowałem też dodać, --line-bufferedale bez sukcesu.

Co robię źle?

Edytować:

Zauważyłem ten sam problem z sedwyjściem jest puste.

Ale na przykład hexdumpkonwertuje tekst na heks na żywo:

$ 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
źródło
2
Może zostaje zbuforowany w rurze? Możesz spróbować użyć stdbuf -o0 netcat localhost 9090 | grep sender(wzięte stąd )
user43791
Czy to tak działa? netcat -z localhost 9090 | grep sender
Gilles Quenot
@ user43791 dane wyjściowe są nadal puste, ale jestem pewien, że netcat zwrócił pasujący ciąg
tomekceszke
@sputnick ten natychmiast wraca do powłoki i nie czeka na wydarzenie
tomekceszke
1
W heksdumpie nie ma żadnych nowych wierszy, więc grepprawdopodobnie nieskończenie czeka na nową linię. catdziała, ponieważ grepdostanie EOF, jeśli nie nowy wiersz, przynajmniej. Może spróbujesz awkz {RS?
muru

Odpowiedzi:

4

Możesz użyć readpolecenia ( bashwbudowanego), aby wymusić czytanie znaków po kolei:

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

Ten skrypt powinien wypisywać wszystkie pełne dane wyjściowe z równoważeniem { i }, ale możesz zmienić skrypt, aby zrobić co chcesz. Ten skrypt NIE poradziłby sobie dobrze w testach porównawczych w porównaniu do prawie wszystkiego, ale jest dość prosty i wydaje się, że działa dla mnie ...

Należy pamiętać, że badana próbka nie ma dopasowania {i }, więc jeśli jest to przypadek rzeczywistego wejścia, może chcesz zmienić kryteria drukować linię.

użytkownik43791
źródło
Wygląda na to, że nawiasy klamrowe są niezgodne tylko dlatego, że opublikował tylko początek danych wyjściowych.
Barmar
8

Odpowiedź jest tutaj: grep nie pasuje do wyjścia nc

netcat wypisuje pełne dzienniki do standardowego błędu, więc musimy przechwytywać błędy przed uruchomieniem potoku do grep.

$ netcat -zv localhost 1-9000 2>&1 | grep succeeded
tkdave
źródło
Ta odpowiedź właśnie mnie rozwiązała. To było bardzo dziwne, kiedy uruchomiłem to polecenie bez 2>&1, wygląda na to, że grep w ogóle nie działał.
Marecky
2

Myślę, że problemem jest brak nowych linii w wynikach netcat. Widzę dwa obejścia:

  1. Wstaw nową linię co xsekundę (z niefortunnymi konsekwencjami, jeśli nowa linia zostanie wstawiona w środku source):

    ( while sleep 1; do echo; done & netcat ... ) | grep source
    
  2. Użyj awkz RS innym niż nowa linia:

    netcat ... | awk -v RS='}' -v ORS='}' '/source/'
    
muru
źródło
Wciąż puste wyjście. Aby upewnić się, że polecenie jest poprawne, uruchamiam na cat netcat_output | awk -v RS='}' -v ORS='}' '/sender/',"sender":"xbmc"}
zrzuconym
Właśnie sprawdziłem pierwsze obejście i działa ! Ale jak wspomniałeś, może podzielić wyniki, więc nie może być ostatecznym rozwiązaniem. W każdym razie wielkie dzięki!
tomekceszke
1

Dodaj, --line-bufferedaby użyć buforowania linii na wyjściu:

netcat localhost 9090 | grep --line-buffered sender 
Cyrus
źródło
Próbowałem już tego, to nie działało.
tomekceszke
1

użyj watchpolecenia:

watch 'netcat localhost 9090 | grep sender'
αғsнιη
źródło
To też nie działa. To samo z sed ... Ale na przykład: netcat localhost 9090 | hexdump działa i zamienia tekst na hex na żywo, dlaczego?
tomekceszke
0

W Bash możesz używać plików pseudo-urządzeń, aby otworzyć połączenie TCP i grepować je jak zwykle. Na przykład:

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

Aby to przetestować, po prostu uruchom serwer, który może wysłać jakiś plik, na przykład:

$ nc -vl 1234 < /etc/hosts

Następnie w innym terminalu uruchom test grepna wyjściu:

$ grep "127" < /dev/tcp/localhost/1234
127.0.0.1   localhost
kenorb
źródło