Безымянные и именованные конвейеры в Linux

Перевод статьи «Pipes and more pipes on Linux».

Системы Linux поддерживают конвейеры, которые позволяют передавать вывод от одной команды к другой. Но они также поддерживают «именованные конвейеры», а это уже нечто иное.

Большинство людей, активно пользующихся командной строкой Linux, быстро переходят к использованию конвейеров. Честно говоря, они и меня привели меня в восторг, когда я впервые использовала командную строку в системе Unix, и спустя десятилетия я продолжаю восхищаться их мощью и удобством.

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

$ cat myposts | grep Linux | wc -l
1456

Эта команда отправляет содержимое файла «myposts» команде grep, ищущей слово «Linux», а затем передает вывод команде wc для подсчета количества строк в выводе.

Как вы, вероятно, подозреваете, конвейеры получили свое название благодаря сходству с промышленными конвейерами. Иногда их также называют «безымянными» или «анонимными» конвейерами, потому что это не единственный вид конвейеров, который предоставляет Linux. К этому мы еще вернемся.

На самом деле, конвейеры настолько полезны, что я часто превращаю некоторые из команд, в которых они используются, в алиасы (псевдонимы), чтобы еще больше упростить их выполнение. Например, показанную ниже команду, которая выводит список всех процессов, связанных с текущей учетной записью, можно добавить в файл .bashrc пользователя:

$ echo 'alias myprocs="ps -ef | grep `whoami`"' >> ~/.bashrc
$ tail -1 ~/.bashrc
alias myprocs="ps -ef | grep `whoami`"

Использование алиаса:

$ myprocs
root        3219     738  0 12:15 ?        00:00:00 sshd: shs [priv]
shs         3229       1  4 12:15 ?        00:00:00 /usr/lib/systemd/systemd --user
shs         3245    3229  0 12:15 ?        00:00:00 (sd-pam)
shs         3269    3219  0 12:15 ?        00:00:00 sshd: shs@pts/0
shs         3284    3269  0 12:15 pts/0    00:00:00 -bash
shs         3319    3284  0 12:15 pts/0    00:00:00 ps -ef
shs         3320    3284  0 12:15 pts/0    00:00:00 grep --color=auto shs

Чтобы видеть только идентификаторы процессов, можно создать алиас, подобный этому:

$ alias myps=”ps aux | grep ^`whoami` | awk '{print $2}'”

Обратите внимание, что он ищет имя пользователя только в первом поле (на это указывает символ ^, обозначающий начало строки, и отображает второе поле. Это гарантирует, что $2 не будет интерпретироваться до тех пор, пока используется псевдоним.

Но конвейеры для передачи вывода одних команд другим не являются единственным видом конвейеров, доступных в Linux. В системах Linux существуют две совершенно разные формы конвейеров: те, что показаны выше, и т. н. «именованные конвейеры».

Именованные конвейеры

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

Именованные конвейеры позволяют процессам взаимодействовать друг с другом. Они создаются как специальные файлы в файловой системе (на это указывает первый символ в длинном листинге — «p»). Другие разрешения указывают, кто может читать или писать в конвейер.

Вот пример создания именованного конвейера с помощью команды mkfifo:

$ mkfifo mypipe
$ ls -l mypipe
prw-r--r--. 1 justme justme 0 Aug  8 13:55 mypipe

Обратите внимание на начальное «p» в выводе: оно указывает на то, что файл является именованным конвейером. Также обратите внимание на 0 в 5-м поле, который показывает, что конвейер не имеет содержимого.

Используя аргумент -m, вы можете установить права на файл, чтобы разрешить другим пользователям писать в конвейер. Обратите внимание, что по умолчанию владелец может читать и писать, а остальные — только читать. Вот пример:

$ mkfifo -m 666 sharedpipe
$ ls -l mypipe0
prw-rw-rw-. 1 shs shs 0 Aug  7 12:50 sharedpipe

Но даже если вы теперь отправите данные в именованный конвейер, он покажется пустым.

$ echo “Here comes some content” > mypipe
$ ls -l mypipe
prw-r--r--. 1 justme justme 0 Aug   13:57 mypipe

Другой процесс может прочитать содержимое с помощью команды, подобной этой:

$ cat mypipe
Here comes some content

Запустив команду, отправляющую данные в конвейер, в фоновом режиме, мы сможем прочитать эти данные с помощью команды cat. Обратите внимание, что в листинге файлов файл по-прежнему пуст, но с помощью команды cat мы можем получить текст один раз. После этого он исчезает. Однако ничто не мешает нам отправить в конвейер больше данных — пока он еще существует.

$ echo "Here comes some content" > mypipe &
[1] 1593
$ ls -l mypipe
prw-r--r--. 1 fedora fedora 0 Aug  5 13:55 mypipe
$ cat mypipe
Here comes some content
[1]+  Done                    echo "Here comes some content" > mypipe
$ cat mypipe
^C

Завершение

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

1 комментарий к “Безымянные и именованные конвейеры в Linux”

  1. Александр

    $ mkfifo -m 666 sharedpipe
    $ ls -l mypipe0
    prw-rw-rw-. 1 shs shs 0 Aug 7 12:50 sharedpipe

    в этом листинге откуда взялось mypipe0?

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх