Чому заміна процесу призводить до файлу під назвою / dev / fd / 63, який є трубкою?


40

Я намагаюся зрозуміти названі труби в контексті цього конкретного прикладу.

Я набираю <(ls -l)свій термінал і отримую вихід як bash: /dev/fd/63: Permission denied.

Якщо я набираю cat <(ls -l), я міг би бачити вміст каталогу. Якщо я замінити catз echo, я думаю , що я отримую ім'я терміналу (або це?).

echo <(ls -l)дає вихід як /dev/fd/63.

Також цей приклад для мене є незрозумілим.

ls -l <(echo "Whatever")
lr-x------ 1 root root 64 Sep 17 13:18 /dev/fd/63 -> pipe:[48078752]

Однак, якщо я даю, ls -l <()він перераховує мені вміст каталогу.

Що відбувається у випадку названої труби?

Відповіді:


37

Коли ви зробите це <(some_command), ваша оболонка виконує команду всередині дужок і замінює все на дескриптор файлу, який підключений до виводу команди. Так /dev/fd/63це труба, що містить вихід вашої дзвінки ls.

Коли ви <(ls -l)отримуєте Permission deniedпомилку, оскільки весь рядок замінюється на трубу, ефективно намагаючись викликати /dev/fd/63як команду, яка не виконується.

У вашому другому прикладі cat <(ls -l)стає cat /dev/fd/63. Коли кішка читає з файлів, заданих як параметри, ви отримуєте вміст. echoз іншого боку, просто виводить свої параметри "як є".

Останній у вас випадок <()просто замінюється нічим, оскільки немає команди. Але це не відповідає між оболонками, в zsh ви все одно отримуєте трубу (хоча порожню).

Підсумок : <(command)дозволяє використовувати команду вихід, де вам, як правило, потрібен файл.

Edit: а Жиль вказує, що це не іменований канал, але анонімний труби. Основна відмінність полягає в тому, що він існує лише до тих пір, поки процес працює, тоді як названа труба (створена, наприклад, за допомогою mkfifo) залишиться без приєднаних до неї процесів.


5
mkfifoстворюється лише названа труба без будь-якого вмісту. Тому вам потрібно написати це самостійно (наприклад mkfifo mypipe; ls > mypipe). І так, запис у трубу буде блокований, поки якийсь процес не зчитується з труби.
кратер2150

6
Тут немає названої труби. /dev/fd/63це анонімна труба.
Жил 'ТАК - перестань бути злим'

1
@ crater2150, @Gilles / dev / fd / 63 справді названа труба. Перевірте це чимось на кшталт file <(ls). Оболонка створює анонімну трубку, але дескриптор файлу відображає як іменовану трубку в /dev/fd. Якби це анонімна труба, вона не мала б імені та не могла б бути відкрита командою, якій /dev/fd/63передається.
rv

2
@rv Це все ще анонімна труба. Той факт, що є ім'я файлу, яке посилається на цю анонімну трубку, не робить його іменованим каналом: названа труба інша, вона існує десь у файловій системі, має дозволи та права власності тощо. Записи /dev/fdможуть стосуватися будь-якого файлу дескриптор, навіть анонімні труби та розетки, мережеві розетки, сегменти спільної пам’яті тощо
Жил 'SO- перестань бути злим'

1
Чому це 63 ?
K3 --- rnc

-4

Ви неправильно розумієте і lsкоманду, і перенаправлення. lsперелічує файли та каталоги, наведені в командному рядку, я не вважаю, що він приймає будь-які дані від stdin. Перенаправлення > >>та <способи використання файлу для введення та збору результатів.


1
Тут немає перенаправлення з файлу. <(…)є процес заміщення.
Жил 'SO- перестань бути злим'

1
@IMSoP - як сказав Жилл, - це не названа труба - її анонімна труба. Він дуже x|yсхожий і майже ідентичний [num]<<REDIRECTу деяких оболонках. Якщо вона відрізняється, це буквальна заміна оболонки на посилання fd - /dev/fd/63і т. Д. І те, що вона робить - або не робить - на stdin. Зробіть echo | readlink /dev/fd/0і подивіться самі.
mikeserv

1
@IMSoP - ось devпосилання - спеціальний файл. ви можете зробити те ж саме / будь-який дескриптор файлів у більшості систем Linux - навіть типово |pipes, хоча я не хочу порушувати поведінку в інших місцях. я дістаюсь, звідки ви родом, але названа труба - це окрема річ для себе - це посилання файлової системи на трубу в ядрі - звичайна посилання на файлову систему, а не файл пристрою.
mikeserv

1
@mikeserv Цікаво, що керівництво Bash згадує, що він буде працювати в системах, не /dev/fd/*створюючи іменовану трубу десь в іншому місці. Але я вважаю, що /dev/fd/*сам по собі інший механізм, ніж названа труба. До речі, опис Вікіпедії може пояснити це розрізнення.
IMSoP

1
@mikeserv Згідно з іншими знайденими нами посиланнями, це простіше, ніж це: якщо /dev/fd/*його немає, bash зробить іменовану трубку /tmpі використовуватиме її замість процесу. Мені це не здається дивним, я просто зробив функціонал доступним у якомога більшій кількості середовищ.
IMSoP
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.