1

I notice that when using tcpdump to read a pcap file, the tcpdump command somehow manages to print information to my console even when I redirect both STDOUT and STDERR. How can I prevent tcpdump from printing "reading from file capture, link type EN10MB (Ethernet)" every time it runs?

For example, the following command prints a line when I expected none:

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

I would like to prevent that line from appearing because it adds unnecessary and unwanted noise to a script's output. I've checked the man page and did not see an option to prevent that message from appearing. I've searched the web for ways to suppress output not captured by STDOUT and STDERR, and found a few hits, but none that I could understand or use in this context.

2 Answers 2

3

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
1
  • Oh, it seems to clear and obvious now that you say it. Thank-you so much. (-:
    – Steve HHH
    Mar 25, 2014 at 2:55
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.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .