Как успокоить вывод tcpdump при чтении файла pcap?

3446
Steve HHH

Я заметил, что при использовании tcpdumpдля чтения файла pcap tcpdumpкоманде каким-то образом удается распечатать информацию на моей консоли, даже когда я перенаправляю как STDOUT, так и STDERR. Как я могу предотвратить tcpdumpпечать " reading from file capture, link type EN10MB (Ethernet)" при каждом запуске?

Например, следующая команда печатает строку, когда я не ожидал ничего:

$ tcpdump -A -r capture.pcap | grep interesting-string > /dev/null 2>&1 reading from file capture.pcap, link-type EN10MB (Ethernet) 

Я хотел бы предотвратить появление этой строки, потому что она добавляет ненужный и нежелательный шум в вывод скрипта. Я проверил справочную страницу и не увидел опции, позволяющей предотвратить появление этого сообщения. Я искал в Интернете способы подавления вывода, не захваченного STDOUT и STDERR, и нашел несколько обращений, но ни одного, которое я мог бы понять или использовать в этом контексте.

1

2 ответа на вопрос

2
Spiff

I think you want to put the output redirection before the pipe, so that it applies to tcpdump's output, not grep's.

tcpdump -A -r capture.pcap 2>&1 | grep interesting-string > /dev/null 
О, это кажется ясным и очевидным теперь, когда вы это говорите. Огромное спасибо. (-: Steve HHH 10 лет назад 0
1

A more detailed version of Spiff's answer:

If you have a pipeline

command1 | command2 

then command 1's standard output, but not its standard error, is redirected to a pipe going to the standard input of command 2.

So if you do

command1 | command2 >/dev/null 2>&1 

that sends the standard output of command 2 to /dev/null, and sends the standard error to the same place the standard output was sent (so that it also goes to /dev/null in this case), but it doesn't do anything with the standard error of command 1, and leaves the standard output of command 1 piped to the standard input of command 2.

However, the command

command1 2>/dev/null | command2 >/dev/null 2>&1 

will send the standard output of command 1 to the standard input of command 2, the standard error of command 1 to /dev/null, and the standard output and error of command 2 to /dev/null, and the command

command1 2>&1 | command2 >/dev/null 2>&1 

will send the standard output of command 1 to the standard input of command 2, the standard error of command 1 to the same place as the standard output of command 1 - i.e., to the standard input of command 2 - and will send the standard output and error of command 2 to /dev/null.

So, for example

tcpdump -A -r capture.pcap 2>&1 | grep interesting-string > /dev/null 2>&1 

will cause grep to see both the standard output and error of tcpdump (so it'll see the reading from file... message, and match it if the interesting string is part of it), and send the standard output and error of grep to /dev/null, so it shouldn't produce any output, it should just give the exit status of grep (which I presume is your intent, i.e. all you want to know is whether the interesting string is part of any of the packets).

BTW, if you are using grep to find out whether a given string is part of its input or not, and don't want any output, try using grep -q if your version of grep supports it; that will run faster, because

  1. grep doesn't have to spend CPU time writing to /dev/null;
  2. grep might quit as soon as it sees the string, so it won't spend any more CPU time reading, and tcpdump will then die with a "Closed pipe" error after grep quits and it won't spend any more CPU time or disk/SSD bandwidth reading from the file.

(Older versions of grep used -s for the same purpose, but the UNIX standard says it's -q, and most UNIX and UNIX-like systems do that now; GNU grep, for example, uses -q.)

Похожие вопросы