Shell – Running tcpdump, tee and scp

pipeshelltcpdump

I'm trying to run the following:

$ tcpdump -l -X -i eth1 -n tcp port <port> | tee capture.txt | \
       scp capture.txt  root@10.3.3.227:/home/checker/
  1. tcpdump -l -X -i eth1 -n tcp port <port>

    In step #1 I'm capturing packets, using "-l" to to make standard out line-buffered, so that it will write each packet as it arrives.

  2. tee capture.txt

    In step #2 man tee: "The tee utility copies standard input to standard output, making a copy in zero or more files." The output is unbuffered.

  3. scp capture.txt root@<remote-IP>:/home/

    In step #3 I'm send the capture.txt file to a remote host.

The problem

If I simply perform steps #1 and #2, ALL packets are captured on the specified port. However, if I also use step #3 the capture.txt does NOT contain all the packets (only a few)… This is killing me because I had this running OK just a few minutes ago!

What is wrong here?

Best Answer

The tee command writes data to the output file as it receives it, but scp copies the file immediately and only copies it once. Since every command in the pipeline runs simultaneously (or nearly so), you only get a few (or no) packets output to the capture.txt file before the file gets copied by scp.

There are a couple ways to do what you seem to want to do.

If you want to copy a few packets from tcpdump, and then transfer the file to the remote host after it finishes, you can use the -c option to terminate tcpdump after it captures that number of packets. Separate your scp command from the pipeline using a semi colon so it gets executed after the tcpdump and tee commands complete:

tcpdump -l -c 10  | tee  /tmp/capture.txt; scp /tmp/capture.txt root@remotehost:/tmp

Or, if you want to see packets in real-time and also copy them in realtime, you could use tee to output the packets to /dev/tty so you can see them, and them pipe them into an ssh command that writes them to a file on the remote host:

tcpdump -l   | tee /dev/tty | ssh root@remotehost "cat > /tmp/capture.txt"

Note that without the -c option here, tcpdump will run until you kill it.

If you wanted the packets stored in a local capture.txt file as well as the remote, you could use multiple tee commands:

tcpdump -l   | tee /tmp/capture.txt | tee /dev/tty | ssh root@remotehost "cat > /tmp/capture.txt"
Related Question