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.