Разница между 'cmd1 | cmd2 'и' cmd2 <(cmd1) 'и' mkfifo foo; cmd1> foo; cmd2 foo '?

Или: Когда и почему не отдавать предпочтение STDIN, когда cmd2 может использовать оба, и является единственной командой?

Я сталкиваюсь с вопросами на этом сайте, где 3 ответа являются одним из каждого из выше, как этот . Этот вопрос имел в качестве первого варианта ответа mkfifo foo; cmd2 foo; cmd2 .

Для меня все 3 соответствующих ответа читаются как функциональные дубликаты с небольшими различиями в семантике под капотом. Всякий раз, когда я это вижу, я задаюсь вопросом, не следовало ли более поздним двум ответам быть отредактированными по отношению к первому, или что-то действительно важное ускользнуло от меня до сих пор.

Вот конкретные примеры (О «Обнюхивании удаленных сетевых устройств через ssh с помощью local wirehark»):

С Fifo, исходный ответ (1) :

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

Ответ (2 ) с (Замена процесса) :

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

Ответ (3), с | (Трубопровод) :

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

Сам обычно довольствуюсь cmd1 | cmd2 версия моих случаев, потому что мне также легче читать последовательно.

Никогда не было причин глубоко копать в деталях, но я смутно могу вспомнить некоторые крайние случаи, касающиеся переменных, области видимости, буферизации, относящейся к суб-оболочкам.

Итак, каковы крайние случаи, когда я должен (не) использовать формы 1,2 или 3?

Примером для (1) может быть то, что процессы могут быть перезапущены индивидуально, если, например, ссылка ssh нестабильна. Но помимо этого я не вижу / не нахожу каких-либо жестких правил, когда не следует отдавать предпочтение типу трубопроводов.

0
19.08.2017, 21:12
1 ответ

Основное различие заключается в том, в какой оболочке выполняются различные команды. Поскольку и ssh, и wiresharkв любом случае являются внешними процессами, семантически не имеет большого значения, какой из них вы используете.

Разница более существенна, если одна или обе команды являются командами оболочки. С mkfifoобе команды выполняются в текущем экземпляре оболочки. При использовании канала обе команды выполняются в подоболочках, разветвленных из вызывающей оболочки. При замене процесса(<(...))wiresharkзапускается текущей оболочкой, а sshзапускается в подоболочке.

Это может повлиять на то, как обрабатываются изменения переменных. Рассмотрим:

  1. x=0; echo foo | { x=1; cat; }; echo "$x"выводит значение 0 для x.
  2. x=0; { x=1; cat; } < <(echo foo); echo "$x"выводит значение 1 дляx

В вашем случае я бы использовал простой конвейер; нет необходимости в нестандартных расширениях -, таких как замена процесса.

ssh remote tcpdump -U -n -s0 <moreOpts> -w - | wireshark -k -i -
1
28.01.2020, 02:45

Теги

Похожие вопросы