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|

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ę.


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

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/'
    

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 

Próbowałem już tego, to nie działało.
tomekceszke

1

użyj watchpolecenia:

watch 'netcat localhost 9090 | grep sender'

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.