Или: Когда и почему не отдавать предпочтение 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 нестабильна. Но помимо этого я не вижу / не нахожу каких-либо жестких правил, когда не следует отдавать предпочтение типу трубопроводов.
Основное различие заключается в том, в какой оболочке выполняются различные команды. Поскольку и ssh
, и wireshark
в любом случае являются внешними процессами, семантически не имеет большого значения, какой из них вы используете.
Разница более существенна, если одна или обе команды являются командами оболочки. С mkfifo
обе команды выполняются в текущем экземпляре оболочки. При использовании канала обе команды выполняются в подоболочках, разветвленных из вызывающей оболочки. При замене процесса(<(...)
)wireshark
запускается текущей оболочкой, а ssh
запускается в подоболочке.
Это может повлиять на то, как обрабатываются изменения переменных. Рассмотрим:
x=0; echo foo | { x=1; cat; }; echo "$x"
выводит значение 0 для x
. x=0; { x=1; cat; } < <(echo foo); echo "$x"
выводит значение 1 дляx
В вашем случае я бы использовал простой конвейер; нет необходимости в нестандартных расширениях -, таких как замена процесса.
ssh remote tcpdump -U -n -s0 <moreOpts> -w - | wireshark -k -i -