Dlaczego podstawienie procesu powoduje utworzenie pliku o nazwie / dev / fd / 63, który jest potokiem?

40

Próbuję zrozumieć nazwane potoki w kontekście tego konkretnego przykładu.

Wpisuję <(ls -l)w moim terminalu i uzyskać wyjście jako, bash: /dev/fd/63: Permission denied.

Po wpisaniu cat <(ls -l)mogłem zobaczyć zawartość katalogu. Jeśli mam wymienić catz echo, myślę uzyskać nazwę terminala (lub nie?).

echo <(ls -l)daje wynik jako /dev/fd/63.

Również ten przykładowy wynik jest dla mnie niejasny.

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

Jeśli jednak dam, ls -l <()wyświetla mi zawartość katalogu.

Co się dzieje w przypadku nazwanej rury?

Ramesh
źródło

Odpowiedzi:

37

Kiedy to zrobisz <(some_command), twoja powłoka wykonuje polecenie w nawiasach i zastępuje całość deskryptorem pliku, który jest podłączony do standardowego wejścia polecenia. Podobnie /dev/fd/63jest z potokiem zawierającym dane wyjściowe twojego wywołania ls.

Gdy <(ls -l)się pojawia Permission denied, pojawia się błąd, ponieważ cała linia jest zastępowana potokiem, skutecznie próbując wywołać /dev/fd/63jako polecenie, które nie jest wykonywalne.

W twoim drugim przykładzie cat <(ls -l)staje sięcat /dev/fd/63 . Gdy kot czyta z plików podanych jako parametry, dostajesz treść. echoz drugiej strony po prostu wypisuje swoje parametry „jak jest”.

Ostatni przypadek, który masz, <()jest po prostu zastępowany przez nic, ponieważ nie ma polecenia. Ale to nie jest spójne między powłokami, w zsh nadal otrzymujesz potok (chociaż pusty).

Podsumowanie : <(command)pozwala użyć wyjścia polecenia, w którym normalnie potrzebujesz pliku.

Edycja: jak wskazuje Gilles , nie jest to nazwany potok, ale anonimowy potok. Główną różnicą jest to, że istnieje tylko, dopóki proces jest uruchomiony, podczas gdy nazwany potok (utworzony np. Za pomocą mkfifo) pozostanie bez dołączonych do niego procesów.

krater2150
źródło
5
mkfifotworzy tylko nazwany potok, bez żadnej zawartości. Więc musisz do niego napisać (np mkfifo mypipe; ls > mypipe.). I tak, zapisy do potoku będą blokowane, dopóki jakiś proces nie odczyta z potoku.
crater2150,
6
Nie ma tu nazwanej rury. /dev/fd/63jest anonimową fajką.
Gilles „SO- przestań być zły”
1
@ crater2150, @Gilles / dev / fd / 63 to rzeczywiście nazwany potok. Sprawdź to za pomocą czegoś takiego file <(ls). Powłoka tworzy anonimowy potok, ale deskryptor pliku jest odzwierciedlany jako potok nazwany /dev/fd. Gdyby był to anonimowy potok, nie miałby nazwy i nie mógłby zostać otwarty poleceniem, do którego /dev/fd/63został przekazany.
rv
2
@rv To wciąż anonimowa rura. Fakt, że istnieje nazwa pliku, która odnosi się do tego anonimowego potoku, nie czyni go nazwanym potokiem: nazwany potok jest inny, istnieje gdzieś w systemie plików, ma uprawnienia i własność itp. Wpisy /dev/fdmogą odnosić się do dowolnego pliku deskryptor, nawet anonimowe potoki i gniazda, gniazda sieciowe, segmenty pamięci wspólnej itp.
Gilles „SO- przestań być zły”
1
Dlaczego to 63 ?
K3 --- rnc
-4

Nie rozumiesz zarówno lspolecenia, jak i przekierowania. lswyświetla listę plików i katalogów podanych w wierszu poleceń, nie sądzę, że akceptuje jakiekolwiek dane wejściowe ze standardowego wejścia. Przekierowanie > >>i <sposoby wykorzystania pliku do wprowadzania danych wejściowych i zbierania danych wyjściowych.

rabarbar
źródło
1
Tutaj nie ma przekierowania z pliku. <(…)jest substytucją procesu.
Gilles „SO- przestań być zły”
1
@IMSoP - jak powiedział Gilles - to nie jest nazwany potok - to anonimowy potok. Jest bardzo podobny x|yi prawie identyczny z [num]<<REDIRECTniektórymi pociskami. Różni się to dosłownym zastąpieniem linku fd przez powłokę - /dev/fd/63i tak dalej, i tym, co robi - lub nie robi - ze standardowym. Zrób echo | readlink /dev/fd/0i przekonaj się sam.
mikeserv
1
@IMSoP - to devlink - specjalny plik. możesz zrobić to samo z dowolnym deskryptorem pliku na większości systemów linuxowych - nawet typowym |pipes, chociaż nie będę ręczyć za zachowanie gdzie indziej. Rozumiem, skąd pochodzisz, ale nazwany potok jest osobną rzeczą dla siebie - jest odniesieniem do systemu plików do potoku w jądrze - zwykłym odniesieniem do systemu plików, a nie plikiem urządzenia.
mikeserv
1
@ mikeserv Co ciekawe, instrukcja Bash wspomina , że będzie działać na systemach bez /dev/fd/*tworzenia nazwanego potoku w innym miejscu. Uważam jednak, że /dev/fd/*sam jest innym mechanizmem niż właściwa nazwana rura. Nawiasem mówiąc, opis Wikipedii może wyjaśnić to rozróżnienie.
IMSoP
1
@mikeserv Według innych źródeł, które znalazłem, jest to prostsze: jeśli /dev/fd/*nie jest dostępne, bash utworzy nazwaną potok /tmpi użyje go zamiast tego do podstawienia procesu. Nie wydaje mi się to takie dziwne, po prostu udostępniam funkcjonalność w jak największej liczbie środowisk.
IMSoP,