Terminate tcpdump in script and continue executing next command

4.8k views Asked by At

I am trying to create a script in which I have:

tcpdump (options) | fgrep (options) > file

After I terminate tcpdump with CTRL+C I want these commands to execute:

sed (options) file | awk (options)
wait
rm file

The first part is getting done but after I press CTRL+C I get thrown to the prompt. I tried with wait, with trap SIGINT, same problem.

Now to get the obvious out of the way: why not simply pipe everything without dumping intermediary unfiltered output to a temporary file? Well I tried that but it seems the information is getting lost in my screen output (busy server, don't know) and I found that breaking the commands like this will allow me to have full output.

UPDATE: Based on the answers I got below, I tried doing it like this, it seemed to be the safest way to make it work:

function1 ()
{
tcpdump (options) | fgrep (options) > file
trap "function2" SIGINT SIGTERM
}

function2 ()
{
sed (options) file | awk (options)
wait
rm -i file
}

It doesn't work. "file" is generated but its content doesn't seem to be read and filtered by the sed | awk syntax after I do CTRL+C and it is not even being deleted by rm command so this is further proof that the secondary, trapped function is not being executed. I don't understand this behavior, am I doing something wrong?

UPDATE 2: The only way I could get it to work properly was like this:

set -m

tcpdump (options) | fgrep (options) > filename &

trap "kill -9 $!" SIGINT

sed (options) filename | mawk (options)

\rm filename

But I could not suppress the output from killing the background process, tried all the solutions I could find: Running bash commands in the background without printing job and process ids - this one makes my trap non-functional; With Bash Scripting, how can I suppress all output from a command? - all the variants from here do not work, I still get output no matter what I do. Tried defining the $! with another variable, tried all variants for /dev/null, tried placing it within the trap command, no use.

1

There are 1 answers

4
Michael Schlottke-Lakemper On BEST ANSWER

Would it work for you to start the tcpdump command in the background and terminate it after a fixed amount of time? E.g. run

(tcpdump (options) | fgrep (options) > file) & 

then get the pid of the process and wait some time,

pid=$! 
sleep 60

and finally kill the command and parse the output

kill -9 $pid
sed (options) file | awk (options)
rm file

Update

If you really want Ctrl-P to stop tcpdump, trap is the way to go. However, after the trapped command is executed, you will always end up at the shell! So the behavior you described is actually what trap is supposed to do.

Thus you could write your trap command as

trap "{ sed (options) file | awk (options); rm file; }" SIGINT SIGTERM

and it should perform all the post-processing on interrupt. If you have more than these simple commands, it might make more sense to put all post-processing commands in a new script or function, e.g.

exec_on_interrupt() {
  sed (options) file | awk (options)
  rm file
  # other stuff...
}

trap "exec_on_interrupt" SIGINT SIGTERM