Perché la sostituzione del processo provoca un file chiamato / dev / fd / 63 che è una pipe?


40

Sto cercando di capire le pipe nominate nel contesto di questo esempio particolare.

Digito <(ls -l)nel mio terminale e ottenere l'output come, bash: /dev/fd/63: Permission denied.

Se digito cat <(ls -l), potrei vedere il contenuto della directory. Se lo sostituisco catcon echo, penso di ottenere il nome del terminale (o è?).

echo <(ls -l)fornisce l'output come /dev/fd/63.

Inoltre, questo esempio di output non mi è chiaro.

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

Tuttavia, se do, ls -l <()mi elenca il contenuto della directory.

Cosa sta succedendo nel caso della pipa denominata?

Risposte:


37

Quando lo fai <(some_command), la tua shell esegue il comando tra parentesi e sostituisce il tutto con un descrittore di file, che è collegato allo stdout del comando. Quindi /dev/fd/63è una pipe che contiene l'output della tua chiamata.

Quando si <(ls -l)ottiene un Permission deniederrore, perché l'intera riga viene sostituita con la pipe, si tenta effettivamente di chiamare /dev/fd/63come comando, che non è eseguibile.

Nel tuo secondo esempio, cat <(ls -l)diventa cat /dev/fd/63. Mentre cat legge dai file forniti come parametri, ottieni il contenuto. echod'altra parte emette semplicemente i suoi parametri "così come sono".

L'ultimo caso che hai, <()è semplicemente sostituito da nulla, in quanto non vi è alcun comando. Ma questo non è coerente tra le shell, in zsh si ottiene comunque una pipe (anche se vuota).

Riepilogo : <(command)consente di utilizzare l'output di un comando, in cui normalmente è necessario un file.

Modifica: come sottolinea Gilles , questa non è una pipe nominata, ma una pipe anonima. La differenza principale è che esiste solo finché il processo è in esecuzione, mentre una pipe denominata (creata ad es. Con mkfifo) rimarrà senza processi collegati ad essa.


5
mkfifocrea solo la pipe denominata, senza alcun contenuto. Quindi devi scriverti da solo (ad es mkfifo mypipe; ls > mypipe.). E sì, le scritture sulla pipe si bloccheranno fino a quando qualche processo non legge dalla pipe.
crater2150,

6
Non esiste una pipe denominata qui. /dev/fd/63è una pipe anonima.
Gilles 'SO- smetti di essere malvagio' il

1
@ crater2150, @Gilles / dev / fd / 63 è davvero una pipa denominata. Controlla questo con qualcosa del genere file <(ls). La shell crea una pipe anonima, ma il descrittore di file si riflette come una pipe con nome /dev/fd. Se fosse una pipe anonima, non avrebbe un nome e non potrebbe essere aperta da un comando a cui /dev/fd/63viene passato.
camper

2
@rv È ancora una pipe anonima. Il fatto che esista un nome file che si riferisce a questa pipe anonima non la rende una pipe con nome: una pipe con nome è diversa, esiste da qualche parte su un filesystem, ha autorizzazioni e proprietà, ecc. Le voci di /dev/fdpossono fare riferimento a qualsiasi file descrittori, anche pipe anonime e prese, prese di corrente di rete, segmenti di memoria condivisa, ecc
Gilles 'SO-tappa è male'

1
Perché è 63 , però?
K3 --- rnc,

-4

Si fraintendono sia il lscomando che il reindirizzamento. lselenca i file e le directory forniti sulla riga di comando, non credo che accetti alcun input da stdin. Reindirizzamento > >>e <sono modi per utilizzare un file per fornire input e raccogliere output.


1
Non c'è reindirizzamento da un file qui. <(…)è una sostituzione di processo.
Gilles 'SO- smetti di essere malvagio' il

1
@IMSoP - come diceva Gilles - non è una pipe nominata - è una pipe anonima. È molto simile x|ye quasi identico a quello [num]<<REDIRECTdi alcune conchiglie. Dove differisce è la sostituzione letterale della shell del collegamento fd - /dev/fd/63ed ecc. E cosa fa - o non fa - con stdin. Fai echo | readlink /dev/fd/0e vedi di persona.
Mikeserv,

1
@IMSoP - questo è un devlink - un file speciale. puoi fare lo stesso con qualsiasi descrittore di file sulla maggior parte dei sistemi Linux - anche tipico |pipes, anche se non garantirò il comportamento altrove. capisco da dove vieni, ma una pipe denominata è una cosa a sé stante - è un riferimento al file system a una pipe nel kernel - un normale riferimento al file system, non un file dispositivo.
Mikeserv,

1
@mikeserv È interessante notare che il manuale di Bash menziona che funzionerà sui sistemi senza /dev/fd/*creare una pipe denominata altrove. Ma prendo in considerazione il fatto che esso /dev/fd/*stesso è un meccanismo diverso rispetto a una pipa denominata propria. Per inciso, la descrizione di Wikipedia potrebbe fare con una spiegazione di questa distinzione.
IMSoP,

1
@mikeserv Secondo altri riferimenti che ho trovato, è più semplice di così: se /dev/fd/*non è disponibile, bash creerà una pipe denominata /tmpe la utilizzerà invece per la sostituzione del processo. Non mi sembra così strano, solo rendere disponibile la funzionalità nel maggior numero possibile di ambienti.
IMSoP,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.