Замена и труба процесса

Мне было интересно, как понять следующее:

Трубопроводная команда команды в stdin другого – мощная техника. Но что делать, если вам нужно передать команду нескольких команд? Здесь происходит замещение процесса.

Другими словами, можно обрабатывать подстановку, какую трубу делать?

Что может обрабатывать замещение, но труба не может?

  • Как ядро ​​отправляет запросы ввода-вывода на жесткий диск?
  • Создайте файл фиксированного размера с определенным содержимым
  • iozone перезаписывает FUSE очень медленно, когда файл больше кэша
  • Linux: Почему init и systemd используют так много операций ввода-вывода?
  • Проблемы с производительностью в GNU / Linux, IO
  • Как я могу контролировать дисковый ввод-вывод в определенном каталоге?
  • Тяжелая активность записи на производительность системы SSD nukes
  • Открытие именованных блоков труб навсегда, если труба удалена без подключения
  • 4 Solutions collect form web for “Замена и труба процесса”

    Хороший способ понять разницу между ними – немного поэкспериментировать с командной строкой. Несмотря на визуальное сходство в использовании символа < , он делает что-то очень отличное от перенаправления или трубы.

    Давайте используем команду date для тестирования.

     $ date | cat Thu Jul 21 12:39:18 EEST 2011 

    Это бессмысленный пример, но он показывает, что cat принял вывод date на STDIN и выплюнул его обратно. Те же результаты могут быть достигнуты путем замещения процесса:

     $ cat <(date) Thu Jul 21 12:40:53 EEST 2011 

    Однако то, что происходило за кулисами, было иным. Вместо того, чтобы получать поток STDIN, cat был фактически передан имя файла, который нужно открыть и прочитать. Вы можете увидеть этот шаг, используя echo вместо cat .

     $ echo <(date) /proc/self/fd/11 

    Когда cat получил имя файла, он читает содержимое файла для нас. С другой стороны, эхо просто показало нам имя файла, в котором оно было передано. Эта разница становится более очевидной, если вы добавляете больше замен:

     $ cat <(date) <(date) <(date) Thu Jul 21 12:44:45 EEST 2011 Thu Jul 21 12:44:45 EEST 2011 Thu Jul 21 12:44:45 EEST 2011 $ echo <(date) <(date) <(date) /proc/self/fd/11 /proc/self/fd/12 /proc/self/fd/13 

    Можно комбинировать подстановку процессов (которая генерирует файл) и перенаправление ввода (которое соединяет файл с STDIN):

     $ cat < <(date) Thu Jul 21 12:46:22 EEST 2011 

    Это выглядит примерно так же, но на этот раз коту передали поток STDIN вместо имени файла. Вы можете увидеть это, попробовав его с помощью эха:

     $ echo < <(date) <blank> 

    Поскольку echo не читает STDIN и аргумент не передается, мы ничего не получаем.

    Трубы и переадресация входных данных загружают содержимое в поток STDIN. Подстановка процесса запускает команды, сохраняет их вывод в специальный временный файл и затем передает это имя вместо команды. Любая команда, которую вы используете, рассматривает ее как имя файла. Обратите внимание, что созданный файл не является обычным файлом, но именованным каналом, который автоматически удаляется, как только он больше не нужен.

    Я должен предположить, что вы говорите о bash или какой-либо другой расширенной оболочке, потому что в оболочке posix нет замены процесса .

    Отчеты справочной страницы bash :

    Замена процесса
    Подстановка процессов поддерживается системами, которые поддерживают именованные каналы (FIFO) или метод / dev / fd для именования открытых файлов. Он принимает форму <(список) или> (список). Список процессов запускается с его вводом или выводом, подключенным к FIFO или некоторому файлу в / dev / fd. Имя этого файла передается в качестве аргумента текущей команде в результате расширения. Если используется форма> (список), запись в файл будет содержать вход для списка. Если используется форма <(список), файл, переданный как аргумент, должен быть прочитан для получения вывода списка.

    Когда доступно, подстановка процесса выполняется одновременно с расширением параметра и переменной, подстановкой команды и арифметическим расширением.

    Другими словами, с практической точки зрения вы можете использовать выражение, подобное следующему

     <(commands) 

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

     while read line; do something; done < <(commands) 

    Возвращаясь к вашему вопросу, мне кажется, что замена процесса и трубы имеют мало общего.

    Если вы хотите последовательно выполнить вывод нескольких команд, вы можете использовать одну из следующих форм:

     (command1; command2) | command3 { command1; command2; } | command3 

    но вы также можете использовать перенаправление при замене процесса

     command3 < <(command1; command2) 

    наконец, если command3 принимает параметр файла (в замене stdin)

     command3 <(command1; command2) 

    Вот три вещи, которые вы можете сделать с заменой процесса, которые невозможны в противном случае.

    Несколько входных процессов

     diff <(cd /foo/bar/; ls) <(cd /foo/baz; ls) 

    Там просто невозможно сделать это с помощью труб.

    Сохранение STDIN

    Скажем, у вас есть следующее:

     curl -o - http://example.com/script.sh #/bin/bash read LINE echo "You said ${LINE}!" 

    И вы хотите запустить его напрямую. Следующее не удается. Bash уже использует STDIN для чтения скрипта, поэтому другой вход невозможен.

     curl -o - http://example.com/script.sh | bash 

    Но этот способ работает отлично.

     bash <(curl -o - http://example.com/script.sh) 

    Замена исходящего процесса

    Также обратите внимание, что замещение процесса работает и наоборот. Таким образом, вы можете сделать что-то вроде этого:

     (ls /proc/*/exe >/dev/null) 2> >(sed -n \ '/Permission denied/ s/.*\(\/proc.*\):.*/\1/p' > denied.txt ) 

    Это немного запутанный пример, но он отправляет stdout в /dev/null , а piping stderr – в sed-скрипт для извлечения имен файлов, для которых была отображена ошибка «Разрешение отказа», и затем отправляет результаты THOSE файл.

    Обратите внимание, что первая команда и перенаправление stdout находятся в круглых скобках ( subhell ), так что только результат команды THAT отправляется в /dev/null и это не путается с остальной частью строки.

    Если команда принимает список файлов в качестве аргументов и обрабатывает эти файлы как входные (или выводимые, но не обычно), каждый из этих файлов может быть именованным каналом или псевдо-файлом / dev / fd, предоставляемым прозрачно путем подстановки процесса:

     $ sort -m <(command1) <(command2) <(command3) 

    Это приведет к «выходу» вывода трех команд для сортировки, поскольку сортировка может содержать список входных файлов в командной строке.

    Interesting Posts
    Linux и Unix - лучшая ОС в мире.