Как получить вывод netcat

13

Я пытаюсь получить доступ к текстовому потоку netcat, но у меня это не работает:

netcat localhost 9090 | grep sender

ничего не возвращает, но я уверен, что должно.

Если я перенаправлю netcatвывод в файл и добавлю некоторые задержки (имитирую реальную среду) - тогда это работает:

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

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

Я также пытался добавить, --line-bufferedно без успеха.

Что я делаю не так?

Редактировать:

Я заметил ту же проблему с sed, выход пуст.

Но, например, hexdumpпреобразует текст в шестнадцатеричный формат:

$ 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
источник
2
Может быть, это буферизуется в трубе? Вы можете попробовать использовать stdbuf -o0 netcat localhost 9090 | grep sender(взято отсюда )
user43791
Это работает так? netcat -z localhost 9090 | grep sender
Жиль Квено
@ user43791 вывод все еще пуст, но я уверен, что netcat вернул совпадающую строку
tomekceszke
@sputnick этот немедленно возвращается в оболочку и не ждет события
tomekceszke
1
В hexdump нет новых строк, поэтому grep, вероятно, бесконечно ждем новой строки. catработает, так grepкак получит EOF, если не новую строку, по крайней мере. Может попробовать awkс , {как RS?
Муру

Ответы:

4

Вы можете использовать readкоманду ( bashвстроенную) для принудительного чтения символов один за другим:

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

Этот скрипт должен печатать каждый полный вывод с балансировкой {и }, но вы можете изменить скрипт так, чтобы он делал все, что вы хотите. Этот сценарий НЕ подходит для теста по сравнению с чем угодно, но он довольно прост и, кажется, работает для меня ...

Обратите внимание, что в вашем тестовом образце не было совпадения, {и }поэтому, если это реальный ввод, вы можете изменить критерии для печати строки.

user43791
источник
Похоже, что несовпадающие скобки только потому, что он опубликовал только начало вывода.
Бармар
8

Ответ здесь: grep не совпадает в выводе nc

netcat выводит подробные журналы со стандартной ошибкой, поэтому нам нужно фиксировать ошибки, прежде чем мы перейдем к grep.

$ netcat -zv localhost 1-9000 2>&1 | grep succeeded
tkdave
источник
Этот ответ только что сделал меня решением. Это было очень странно, когда я запускаю эту команду без 2>&1, похоже, что grep вообще не работает.
Мареки
2

Я думаю, что проблема заключается в отсутствии новых строк в netcatвыводе. Я вижу два обходных пути:

  1. Вставлять новую строку каждые xсекунды (с печальными последствиями, если новая строка вставляется в середине source):

    ( while sleep 1; do echo; done & netcat ... ) | grep source
    
  2. Используйте awkс RS, кроме newline:

    netcat ... | awk -v RS='}' -v ORS='}' '/source/'
    
Мур
источник
Все еще пустой вывод. Чтобы убедиться, что команда верна, я запускаю дамп-поток - cat netcat_output | awk -v RS='}' -v ORS='}' '/sender/'вывод был в порядке:,"sender":"xbmc"}
tomekceszke
Я только что проверил первый обходной путь, и он работает ! Но, как вы упомянули, он может разделить вывод, поэтому он не может быть окончательным решением. В любом случае большое спасибо!
tomekceszke
1

Добавьте --line-bufferedдля использования буферизации строки на выходе:

netcat localhost 9090 | grep --line-buffered sender 
Кир
источник
Я уже попробовал это, это не сработало.
tomekceszke
1

используйте watchкоманду:

watch 'netcat localhost 9090 | grep sender'
αғsнιη
источник
Это тоже не работает. То же самое с sed ... Но, например, это: netcat localhost 9090 | hexdump работает и заменяет текст на hex live, почему?
tomekceszke
0

В Bash вы можете использовать файлы псевдоустройств, чтобы открыть TCP-соединение и выполнить его как обычно. Например:

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

Чтобы проверить это, просто запустите сервер, который может отправить некоторый файл, например:

$ nc -vl 1234 < /etc/hosts

Затем в другом терминале запустите тест до grepвыхода:

$ grep "127" < /dev/tcp/localhost/1234
127.0.0.1   localhost
kenorb
источник