Можно ли перенаправить вывод команды более чем в одну команду?

21

Насколько я знаю, я могу использовать команду tee, чтобы разделить стандартный вывод на экран и другие файлы:

command -option1 -option2 argument | tee file1 file2 file3 

Можно ли перенаправить вывод в команды вместо файлов, используя tee, чтобы я теоретически мог создать цепочку команд?

Абдул Аль Хазред
источник
3
Объясните, что вы подразумеваете под «выходным сигналом», и опишите, что вы подразумеваете под созданием «сети команд».
Янис
В Linux каждая команда имеет один вход и два выхода. они помечены 0 (для ввода), 1 (для вывода) и 2 (для вывода ошибки). Я думал о 1, когда я сказал «выходной сигнал», потому что я прочитал, что команда tee разделяет только выходные данные, помеченные 1. Когда я сказал «сеть команд», я не был очень техническим, я не уверен, как сеть определена правильно из с математической точки зрения, но я просто думал о дереве команд, типологически говоря, так что некоторые команды могут быть родителями более чем одной дочерней команды.
Абдул Аль Хазред
Спасибо за ваше разъяснение. Пожалуйста, не используйте слово «сигнал», так как оно имеет определенное значение в Unix, и в этом контексте термин вводит в заблуждение. Еще раз спасибо.
Янис
В командной строке введите man -k signal, чтобы узнать особое значение этого ключевого понятия в UNIX и Linux. man kill будет хорошей страницей для начала.
Роб
Кроме того, многие люди называют stdin stdout и stderr входными или выходными «потоками». Есть как небольшие реки данных, следовательно, поток. Вы были правы, когда ухватились за слово, чтобы описать их коллективно, но сигнал - просто неправильное слово.
Роб

Ответы:

25

Вы можете использовать именованные каналы ( http://linux.die.net/man/1/mkfifo ) в командной строке teeи иметь команды, читающие на именованных каналах.

mkfifo /tmp/data0 /tmp/data1 /tmp/data2
cmd0 < /tmp/data0 & cmd1 < /tmp/data1 & cmd2 < /tmp/data2 &
command -option1 -option2 argument | tee /tmp/data0 /tmp/data1 /tmp/data2

Когда commandзакончится, teeзакроет именованные каналы, которые будут сигнализировать EOF (чтение 0 байтов) на каждом из /tmp/dataNкоторых обычно завершит cmdNпроцессы. Реальный пример:

$ mkfifo /tmp/data0 /tmp/data1 /tmp/data2
$ wc -l < /tmp/data0 & wc -w < /tmp/data1 & wc -c < /tmp/data2 &
$ tee /tmp/data0 /tmp/data1 /tmp/data2 < /etc/passwd >/dev/null
$ 61
1974
37

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

Arcege
источник
1
В bash вы можете безопасно печатать через /tmp/data/{0,1,2}. Опять же, в bash вы можете использовать процесс подстановки и mkfifoполностью пропустить
Тобиас Кинцлер
2
Возможно, вы захотите изменить / dev / data0 на / tmp / data0. Кроме того, спасибо за ответ на вопрос в неявной форме. Это более полезно, чем предполагать, что все используют bash.
Абонет
15

Если я правильно понимаю, вы ищете эквивалент tee file1 file2 file3, но вместо того, чтобы записывать одни и те же данные в три файла file1, file2и file3вы хотите разделить одни и те же данные на три команды cmd1, cmd2и cmd3, т.е.

… | ??? cmd1 cmd2 cmd3

должно быть эквивалентно

… | cmd1 &
… | cmd2 &
… | cmd3 &

за исключением того, что будет выполнено только один раз.

Есть два способа сделать это.

Ksh93, bash и zsh поддерживают процесс подстановки . Это обобщение каналов, которое позволяет аргументу команды быть файлом, который при записи в него передает данные в качестве входных данных для команды (также существует вариант ввода, который при чтении из него получает данные, выводимые командой) , То есть,

echo hello | tee >(cmd1)

печатает helloна стандартный вывод и дополнительно работает cmd1с helloвводом.

Так, например, если вы хотите дублировать ввод somecommandи передать его обоим cmd1и cmd2, вы можете использовать

somecommand | tee >(cmd1) | cmd2

Если ваша оболочка не поддерживает подстановку процессов, вы можете использовать именованные каналы. Посмотрите ответ Арсеге о том, как это работает. Именованные каналы менее удобны, чем подстановка процессов, потому что их нужно создавать и удалять, а также запускать и синхронизировать процессы вручную. Их преимущество в том, что они полностью переносимы, в то время как не все оболочки поддерживают процессные замены. Они также могут использоваться в сценариях, отличных от тех, для которых предназначена замена процесса.

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

Жиль "ТАК - перестань быть злым"
источник
5
Смотрите также peeиз moreutils.
Стефан Шазелас
Обратите внимание, что замена процесса была введена ksh88.
Стефан Шазелас
6

По крайней мере, в вы можете пропустить, mkfifoиспользуя подстановку процесса:

command -option1 -option2 argument | tee >(cmd1) >(cmd2) >(cmd3)

или принять пример Арцежа

tee >(wc -l) >(wc -w) >(wc -c) < /etc/passwd >/dev/null
Тобиас Кинцлер
источник