0
votes

I am automating some work that requires calling tcpdump -nn -tt -r on some .pcap files.

To do this I"m using the following tcl code:

set magic_dir "results/pcap/";
set magic_filename "data"
set magic_node_count 16
set magic_command "tcpdump"

for {set i 0} {$i <= $magic_node_count} {incr i} \
  {
    set filename "${magic_dir}${magic_filename}-${i}-0.pcap"
    if {[file exists $filename]} \
      {
        set dest_dir "${magic_dir}\.\./tmp/tmp_${i}"
        exec ${magic_command} -nn -tt -r ${filename} > ${dest_dir}
      } \
  }

This works (the first file gets converted) but tcl reports an error in that line. The same thing happens later on in the script when I attempt to use grep. I avoid this by using catch but I would like to know how to properly use this command.

1
Lots of useful discussion at wiki.tcl.tk/exec - glenn jackman
So grep and tcpdump are writing to stderr and tcl thinks it's an error? I am not sure I understand what is the general lesson with exec but my script appears to be working perfectly with catch at this time. - AturSams
If you don't consider the command outputting to stderr a problem, use exec -ignorestderr -- tcl.tk/man/tcl8.5/TclCmd/exec.htm - glenn jackman

1 Answers

2
votes

By default, Tcl's exec generates an error if either

  1. The command has a non-zero exit code, or
  2. The command produces output on its standard error channel.

Of these two, you pretty much have to handle the first by using catch (or try/trap in Tcl 8.6) since that's almost always a genuine error. (Or not; grep is a classic problem.) But with standard error processing, you've got more options (assuming you're using 8.5).

For example, you can redirect to the terminal:

exec ${magic_command} -nn -tt -r ${filename} > ${dest_dir} 2>/dev/tty

or to the normal standard error channel:

exec ${magic_command} -nn -tt -r ${filename} > ${dest_dir} 2>@stderr

or you can just tell Tcl to throw it away:

exec -ignorestderr ${magic_command} -nn -tt -r ${filename} > ${dest_dir}

or even combine it into the standard output:

exec ${magic_command} -nn -tt -r ${filename} > ${dest_dir} 2>@1

You can get more exotic by introducing extra pipelines (e.g., with 8.6's chan pipe or through trickiness with an external cat -u) but that starts to get really complicated fast. Since you're automating tcpdump, you may well be best off just combining everything into one and working with that. Or using considerably-greater power and sophistication of the Expect package.