0

Or: When and why to not prefer STDIN when cmd2 can use both, and is a single command?

I come across questions on this site, where 3 of their answers are one of each of the above, like this one. This question had as first answer variant mkfifo foo; cmd2 foo; cmd2<foo.

To me the concerned 3 answers all read like functional duplicates with slight differences in semantics under the hood. Whenever I see that, I wonder whether the later 2 answers should rather have been edits to the first one, or whether something really significant has eluded me up to now.

Here are the specific examples (About "Sniffing remote network devices via ssh with local wireshark"):

With Fifo, original answer(1):

$ mkfifo /tmp/remote; wireshark -k -i /tmp/remote
$ ssh remote "tcpdump -s 0 -U -n -w - <moreOpts>" > /tmp/remote

Answer (2) with <(...) (Process substitution):

$ wireshark -k -i <(ssh remote tcpdump -s0 -U -n -w - <moreOpts>)

Answer (3), with | (Piping):

$ ssh remote tcpdump -U -n -s0 <moreOpts> -w - | wireshark -k -i -

I myself usually settle for the cmd1 | cmd2 version my cases, because I also find it easier to read sequentially.

There was never reason to dig real deep for specifics, but I can vaguely remember some edge cases regarding variables, scope, buffering regarding sub-shells.

So, what are the edge cases, when I should|could (not) use forms 1,2, or 3?

An example for (1) would be, that the processes can be restarted individually, if e.g. the ssh link is flaky. But apart from that I don't see/find any hard and fast rules, on when not to prefer type piping.

1

The main difference is which shell the various commands run in. Since both ssh and wireshark are external processes anyway, it makes little difference semantically which one you use.

The difference is more relevant if one or both commands are shell commands. With mkfifo, both commands run in the current shell instance. With a pipe, both commands run in subshells forked from the calling shell. With the process substitution (<(...)), wireshark is started by the current shell, but ssh is started in a subshell.

This can affect how changes to variables are handled. Consider:

  1. x=0; echo foo | { x=1; cat; }; echo "$x" outputs a value of 0 for x.
  2. x=0; { x=1; cat; } < <(echo foo); echo "$x" outputs a value of 1 for x

In your case, I would use the simple pipeline; no need for non-standard extensions like process substitution.

ssh remote tcpdump -U -n -s0 <moreOpts> -w - | wireshark -k -i -

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.