Domanda Qual è la differenza tra "Reindirizzamento" e "Tubo"?


Questa domanda può sembrare un po 'stupida, ma non riesco davvero a vedere la differenza tra reindirizzamento e pipe.

Il reindirizzamento viene utilizzato per reindirizzare lo stdout / stdin / stderr, ad es. ls > log.txt.

I pipe vengono utilizzati per fornire l'output di un comando come input a un altro comando, ad es. ls | grep file.txt.

Ma perché ci sono due operatori per la stessa cosa?

Perché non scrivere solo ls > grep passare l'output, non è anche solo una sorta di reindirizzamento? Cosa mi manca?


173
2017-08-07 13:22


origine




risposte:


Pipe è usato per passare l'output a un altro programma o utilità.

Il reindirizzamento è usato per passare l'output a uno file o flusso.

Esempio: thing1 > thing2 vs thing1 | thing2

thing1 > thing2

  1. La tua shell eseguirà il programma chiamato thing1
  2. Tutto ciò che thing1 le uscite saranno collocate in un file chiamato thing2. (Nota - se thing2 esiste, sarà sovrascritto)

Se si desidera passare l'output dal programma thing1 a un programma chiamato thing2, puoi fare quanto segue:

thing1 > temp_file && thing2 < temp_file

quale sarebbe

  1. eseguire il programma denominato thing1
  2. salva l'output in un file chiamato temp_file
  3. eseguire il programma denominato thing2, fingendo che la persona alla tastiera abbia digitato il contenuto di temp_file come input

Tuttavia, questo è goffo, quindi hanno fatto pipe come un modo più semplice per farlo. thing1 | thing2 fa la stessa cosa di thing1 > temp_file && thing2 < temp_file

MODIFICA per fornire maggiori dettagli alla domanda nel commento:

Se > ha cercato di essere sia "pass to program" che "write to file", potrebbe causare problemi in entrambe le direzioni.

Primo esempio: Stai provando a scrivere su un file. Esiste già un file con quel nome che desideri sovrascrivere. Tuttavia, il file è eseguibile. Presumibilmente, cercherebbe di eseguire questo file, passando l'input. Dovresti fare qualcosa come scrivere l'output su un nuovo nome file, quindi rinominare il file.

Secondo esempio: Come ha fatto notare Florian Diesch, e se c'è un altro comando nel sistema con lo stesso nome (cioè nel percorso di esecuzione). Se intendevi creare un file con quel nome nella tua cartella attuale, verrai bloccato.

In terzo luogo: se digiti male un comando, non ti avviserà che il comando non esiste. In questo momento, se digiti ls | gerp log.txt te lo dirà bash: gerp: command not found. Se > significava entrambi, sarebbe semplicemente creare un nuovo file per te (quindi avvisare che non sa cosa fare con log.txt).


194
2017-08-07 13:30



Grazie. Hai nominato thing1 > temp_file && thing2 < temp_file fare più facile con i tubi. Ma perché non riutilizzare il > operatore per fare questo, ad es. thing1 > thing2 per i comandi thing1 e thing2 ? Perché un operatore extra | ? - John Threepwood
"Prendere l'output e scriverlo su un file" è un'azione diversa da "Prendi l'output e passa a un altro programma". Modificherò più pensieri nella mia risposta ... - David Oneill
@ John Woodwood Hanno diversi significati. Cosa succede se volessi reindirizzare qualcosa a un file chiamato less, per esempio? thing | less e thing > less sono perfettamente diversi, come fanno cose diverse. Quello che proponi creerebbe un'ambiguità. - Darkhogg
È esatto dire che "cosa1> temp_file" è semplicemente zucchero sintattico per "cosa1 | tee temp_file"? Da quando ho scoperto di tee non utilizzo quasi mai i reindirizzamenti. - Sridhar-Sarnobat
@ Sridhar-Sarnobat no, il tee il comando fa qualcosa di diverso. tee scrive l'output su entrambi gli schermi (stdout) e il file. Reindirizzamento fa solo il file. - David Oneill


Se il significato di foo > bar dipenderebbe dall'esistenza di un comando chiamato bar ciò renderebbe l'uso del reindirizzamento molto più difficile e più incline agli errori: ogni volta che voglio reindirizzare a un file, prima dovevo controllare se c'è un comando chiamato come il mio file di destinazione.


19
2017-08-07 13:40



Questo sarebbe un problema solo se stai scrivendo bar in una directory che fa parte del tuo $PATH variabile env. Se ti trovi in ​​qualcosa come / bin, allora ot potrebbe essere un problema. Ma anche allora bar dovrebbe avere un set di autorizzazioni eseguibili, in modo che i controlli di shell non solo per trovare un eseguibile bar ma in realtà può eseguirlo. E se la preoccupazione è con la sovrascrittura del file esistente, noclober l'opzione shell dovrebbe impedire la sovrascrittura dei file esistenti nei reindirizzamenti. - Sergiy Kolodyazhnyy


C'è una differenza fondamentale tra i due operatori:

  1. ls > log.txt -> Questo comando invia l'output al file log.txt.

  2. ls | grep file.txt -> Questo comando invia l'output del comando ls a grep tramite l'uso di pipe (|), e il comando grep cerca file.txt nell'input fornito dal comando precedente.

Se dovessi eseguire la stessa operazione usando il primo scenario, allora sarebbe:

ls > log.txt; grep 'file.txt' log.txt

Quindi una pipa (con |) viene utilizzato per inviare l'output ad altri comandi, mentre il reindirizzamento (con >) viene utilizzato per reindirizzare l'output su un file.


11
2017-08-07 13:32





Dal manuale di amministrazione del sistema Unix e Linux:

reindirizzamento

La shell interpreta i simboli <,> e >> come istruzioni per reindirizzare a comando di input o output ao da a file.

Pipes

Per connettere lo STDOUT di uno comando allo STDIN di un altro ud B B Bud Bud Bud tutte Budud B B Bud B B B B B B B B B B B simbolo, comunemente noto come un tubo.

Quindi la mia interpretazione è: se è un comando da comandare, usa una pipe. Se si sta eseguendo l'output su o da un file, utilizzare il reindirizzamento.


9
2018-02-16 00:40





C'è una grande differenza sintattica tra i due:

  1. Un reindirizzamento è un argomento per un programma
  2. Una pipe separa due comandi

Puoi pensare a reindirizzamenti come questo: cat [<infile] [>outfile]. Ciò implica che l'ordine non ha importanza: cat <infile >outfile equivale a cat >outfile <infile. Puoi persino mescolare i reindirizzamenti con altri argomenti: cat >outfile <infile -b e cat <infile -b >outfile sono entrambi perfettamente bene. Inoltre è possibile mettere insieme più di un input o output (gli input verranno letti in sequenza e tutti gli output verranno scritti su ciascun file di output): cat >outfile1 >outfile2 <infile1 <infile2. La destinazione o la fonte di un reindirizzamento può essere un nome file o il nome di un flusso (come & 1, almeno in bash).

Ma i pipe separano completamente un comando da un altro comando, non puoi mescolarli con gli argomenti:

[command1] | [command2]

La pipe prende tutto ciò che è scritto sullo standard output da command1 e lo invia allo standard input di command2.

Puoi anche combinare piping e reindirizzamento. Per esempio:

cat <infile >outfile | cat <infile2 >outfile2

Il primo cat leggerà le righe da infile, quindi scriverà contemporaneamente ogni riga in outfile e la invierà al secondo cat.

Nel secondo cat, lo standard input prima legge dalla pipe (il contenuto di infile), quindi legge da infile2, scrivendo ogni riga su outfile2. Dopo aver eseguito ciò, il file di output sarà una copia di infile e outfile2 conterrà l'infile seguito da infile2.

Infine, in realtà fai qualcosa di veramente simile al tuo esempio usando il reindirizzamento "here string" (solo famiglia bash) e i backtick:

grep blah <<<`ls`

darà lo stesso risultato di

ls | grep blah

Ma penso che la versione di reindirizzamento leggerà prima tutto l'output di ls in un buffer (in memoria), e quindi alimenterà quel buffer a grep una riga alla volta, mentre la versione con pipe prenderà ogni riga da ls come emerge, e passare quella linea a grep.


3
2017-08-23 22:24



Nitpick: l'ordine è importante nel reindirizzamento se si reindirizza un fd a un altro: echo yes 1>&2 2>/tmp/blah; wc -l /tmp/blah; echo yes 2>/tmp/blah 1>&2; wc -l /tmp/blah Inoltre, il reindirizzamento a un file utilizzerà solo l'ultimo reindirizzamento. echo yes >/tmp/blah >/tmp/blah2 scriverò solo a /tmp/blah2. - muru
Il reindirizzamento non è in realtà un argomento per il programma. Il programma non saprà né si preoccuperà del suo output (o dell'ingresso). È solo un modo per dire a Bash come organizzare le cose prima di eseguire il programma. - Alois Mahdal


Per aggiungere alle altre risposte, ci sono anche sottili differenze semantiche - per es. i tubi si chiudono più facilmente dei reindirizzamenti:

seq 5 | (head -n1; head -n1)                # just 1
seq 5 > tmp5; (head -n1; head -n1) < tmp5   # 1 and 2
seq 5 | (read LINE; echo $LINE; head -n1)   # 1 and 2

Nel primo esempio, quando la prima chiamata a head finisce, chiude la pipa, e seq termina, quindi non c'è input disponibile per il secondo head.

Nel secondo esempio, la testa consuma la prima riga, ma quando si chiude è proprio stdin  tubo, il file rimane aperto per la prossima chiamata da utilizzare.

Il terzo esempio mostra che se usiamo read per evitare di chiudere la pipe è ancora disponibile all'interno del sottoprocesso.

Quindi lo "stream" è la cosa che noi trasmettiamo dati attraverso (stdin ecc.) Ed è lo stesso in entrambi i casi, ma la pipe collega flussi da due processi, dove un reindirizzamento collega uno stream tra un processo e un file, quindi tu può vedere la fonte di entrambe le somiglianze e differenze.

Post scriptum Se sei così curioso e / o sorpreso da quegli esempi come me, puoi approfondire l'utilizzo trap per vedere come si risolvono i processi, E.g:

(trap 'echo seq EXITed >&2' EXIT; seq 5) | (trap 'echo all done' EXIT; (trap 'echo first head exited' EXIT; head -n1)
echo '.'
(trap 'echo second head exited' EXIT; head -n1))

A volte il primo processo si chiude prima 1 viene stampato, a volte in seguito.

Ho anche trovato interessante da usare exec <&- chiudere il flusso dal reindirizzamento per approssimare il comportamento del tubo (anche se con un errore):

seq 5 > tmp5
(trap 'echo all done' EXIT
(trap 'echo first head exited' EXIT; head -n1)
echo '.'
exec <&-
(trap 'echo second head exited' EXIT; head -n1)) < tmp5`

2
2018-06-05 00:54



"quando finisce il primo call to head, chiude il pipe" Questo è in realtà inaccurato per due motivi. Uno, (head -n1; head -n1) è subshell con due comandi, ognuno dei quali eredita leggere end of pipe come descrittore 0, e quindi subshell E ogni comando ha quel descrittore di file aperto. Seconda ragione, potete vederlo con strace -f bash -c 'seq 5 | (testa -n1; testa -n1) '. Quindi il primo capo chiude solo la sua copia del descrittore di file - Sergiy Kolodyazhnyy
Anche il terzo esempio è impreciso, perché read consuma solo la prima riga (questo è un byte per 1 e newline). seq inviato in totale 10 byte (5 numeri e 5 newline). Quindi ci sono 8 byte rimanenti nel buffer pipe, ed è per questo che secondo head funziona - ci sono ancora dati disponibili nel buffer pipe. A proposito, la testa esce solo se c'è 0 byte letti, un po 'come in head /dev/null - Sergiy Kolodyazhnyy
Grazie per il chiarimento. Sto comprendendo correttamente questo in seq 5 | (head -n1; head -n1)la prima chiamata svuota la pipe, quindi esiste ancora in uno stato aperto ma senza dati per la seconda chiamata a head? Quindi la differenza di comportamento tra la pipe e il redirect è dovuta al fatto che head estrae tutti i dati dalla pipe, ma solo le 2 righe fuori dal file gestiscono? - Julian de Bhal
È corretto. Ed è qualcosa che può essere visto con strace comando che ho dato nel primo commento. Con il reindirizzamento, il file tmp è sul disco che lo rende ricercabile (perché lo usano lseek() syscall - i comandi possono saltare attorno al file dal primo all'ultimo byte come vogliono. Ma i tubi sono sequenziali e non ricercabili. Quindi l'unico modo per fare il suo lavoro è leggere prima tutto, o se il file è grande - mapparne un po 'alla RAM tramite mmap() chiamata. Una volta ho fatto il mio tail in Python, e ha incontrato esattamente lo stesso problema. - Sergiy Kolodyazhnyy
È anche importante ricordare che read end of the pipe (descrittore di file) viene dato prima a subshell (...)e la subshell eseguirà una copia del proprio stdin in ogni comando interno (...). Quindi sono tecnicamente letti dallo stesso oggetto. Primo head  pensa che stia leggendo dal proprio stdin. Secondo head pensa che abbia il suo stdin. Ma in realtà il loro fd # 1 (stdin) è solo una copia della stessa fd, che viene letta alla fine della pipe. Inoltre, ho postato una risposta, quindi forse aiuterà a chiarire le cose. - Sergiy Kolodyazhnyy


Nota: la risposta riflette la mia comprensione di questi meccanismi aggiornata, accumulata sulla ricerca e sulla lettura delle risposte dei peer su questo sito e unix.stackexchange.come sarà aggiornato col passare del tempo. Non esitate a fare domande o suggerire miglioramenti nei commenti. Suggerisco anche di provare a vedere come funzionano i syscalls con strace comando. Inoltre, per favore, non essere intimidito dalla nozione di internals o syscalls - non devi sapere o essere in grado di usarli per capire come la shell fa le cose, ma sicuramente aiutano a capire.

TL; DR

  • | le pipe non sono associate a una voce su disco, quindi non hai un inode numero di filesystem del disco (ma hanno inode in pipefs file system virtuale nello spazio del kernel), ma i reindirizzamenti spesso coinvolgono file, che hanno voci del disco e quindi hanno inode corrispondente.
  • i tubi non lo sono lseek()'In modo che i comandi non possano leggere alcuni dati e quindi riavvolgere, ma quando si reindirizza con > o < di solito è un file che è lseek() oggetto in grado, in modo che i comandi possano navigare comunque a loro piacimento.
  • i reindirizzamenti sono manipolazioni sui descrittori di file, che possono essere molti; le pipe hanno solo due descrittori di file: uno per il comando sinistro e uno per il comando destro
  • il reindirizzamento su stream e pipe standard sono entrambi bufferizzati.
  • i tubi comportano quasi sempre biforcazioni, reindirizzamenti - non sempre
  • i pipe gestiscono sempre i descrittori di file, i reindirizzamenti - utilizzano file effettivi con nome file su disco o descrittori di file.
  • pipe è un metodo di comunicazione tra processi, mentre i reindirizzamenti sono solo manipolazioni su file aperti o oggetti simili a file
  • entrambi impiegano dup2() syscalls sotto il cofano per fornire copie dei descrittori di file, in cui si verifica il flusso effettivo di dati.
  • i reindirizzamenti possono essere applicati "globalmente" con exec comando integrato (vedi Questo e Questo ), quindi se lo fai exec > output.txt ogni comando scriverà a output.txt da allora in poi. | le pipe vengono applicate solo per il comando corrente (che significa sia un semplice comando che una subshell) seq 5 | (head -n1; head -n2)o comandi composti.
  • Quando il reindirizzamento è fatto su file, cose come echo "TEST" > file e echo "TEST" >> file entrambi usano open() syscall su quel file (Guarda anche) e ottenere il descrittore di file da esso per passarlo a dup2(). Pipes | usare solo pipe() e dup2() syscall.

introduzione

Per capire come questi due meccanismi differiscono, è necessario comprendere le loro proprietà essenziali, la storia dietro le due e le loro radici nel linguaggio di programmazione C. In effetti, conoscendo quali sono i descrittori dei file e come dup2() e pipe() le chiamate di sistema lavoro è essenziale, così come lseek(). Shell è inteso come un modo per rendere questi meccanismi astratti all'utente, ma scavare più in profondità rispetto all'astrazione aiuta a comprendere la vera natura del comportamento della shell.

Le origini di reindirizzamenti e pipe

Secondo l'articolo di Dennis Ritche Petroglifi profetici, tubi originati da a 1964 promemoria interno di Malcolm Douglas McIlroy, nel momento in cui stavano lavorando Sistema operativo Multics. Citazione:

Per riassumere in breve le mie più forti preoccupazioni:

  1. Dovremmo avere alcuni modi per collegare programmi come il tubo da giardino - avvitare un altro segmento quando diventa quando è necessario massaggiare i dati in un altro modo. Anche questo è il modo di IO.

Ciò che è evidente è che al momento i programmi erano in grado di scrivere su disco, tuttavia ciò era inefficiente se l'output era grande. Per citare la spiegazione di Brian Kernighan in Pipeline Unix video :

Innanzitutto, non è necessario scrivere un programma di grandi dimensioni: esistono programmi più piccoli esistenti che potrebbero già svolgere parte del lavoro ... Un altro è che è possibile che la quantità di dati che si sta elaborando non sia adatta se lo hai archiviato in un file ... perché ricordi, siamo tornati ai tempi in cui i dischi su queste cose avevano, se sei stato fortunato, un Megabyte o due di dati ... Quindi la pipeline non ha mai dovuto istanziare l'intero output .

Quindi la differenza concettuale è evidente: le pipe sono un meccanismo per far dialogare i programmi tra loro. Reindirizzamenti: è un modo di scrivere su file a livello base. In entrambi i casi, shell rende queste due cose facili, ma al di sotto del cappuccio, c'è molto da fare.

Andando più in profondità: syscalls e meccanismi interni della shell

Iniziamo con la nozione di descrittore di file. I descrittori di file descrivono fondamentalmente un file aperto (che si tratti di un file su disco o in memoria o di un file anonimo), che è rappresentato da un numero intero. Il due flussi di dati standard  (stdin, stdout, stderr) sono i descrittori di file 0,1 e 2 rispettivamente. Da dove vengono ? Bene, nei comandi shell i descrittori di file sono ereditati dalla shell genitore. Ed è vero in generale per tutti i processi - il processo figlio eredita i descrittori di file del genitore. Per demoni è comune chiudere tutti i descrittori di file ereditati e / o reindirizzare ad altri luoghi.

Torna al reindirizzamento. Cos'è veramente? È un meccanismo che indica alla shell di preparare i descrittori di file per il comando (poiché i reindirizzamenti vengono eseguiti dalla shell prima dell'esecuzione dei comandi) e li indirizza dove l'utente ha suggerito. Il definizione standard di reindirizzamento dell'output

[n]>word

Quella [n] c'è il numero del descrittore del file. Quando lo fai echo "Something" > /dev/null il numero 1 è implicito lì, e echo 2> /dev/null.

Sotto il cofano ciò avviene duplicando il descrittore di file tramite dup2() chiamata di sistema. Prendiamo df > /dev/null. La shell creerà un processo figlio dove df corre, ma prima si aprirà /dev/null come descrittore di file n. 3 e dup2(3,1) sarà rilasciato, il che rende una copia del descrittore di file 3 e la copia sarà 1. Sapete come avete due file file1.txt e file2.txte quando lo fai cp file1.txt file2.txt avrai due file uguali, ma puoi manipolarli in modo indipendente? È piuttosto la stessa cosa che succede qui. Spesso puoi vedere che prima di correre, il bash andrà bene dup(1,10) per fare un descrittore # 1 del file di copia che è stdout (e quella copia sarà fd # 10) per ripristinarla più tardi. È importante notare che quando si considera comandi incorporati (che fanno parte della shell stessa e non hanno file in /bin o altrove) o comandi semplici in shell non interattiva, la shell non crea un processo figlio.

E poi abbiamo cose come [n]>&[m] e [n]&<[m]. Questo è duplicazione di descrittori di file, che hanno lo stesso meccanismo di dup2() solo ora è nella sintassi della shell, opportunamente disponibile per l'utente.

Una delle cose importanti da notare sul reindirizzamento è che il loro ordine non è fisso, ma è significativo al modo in cui la shell interpreta ciò che l'utente desidera. Confronta il seguente:

# Make copy of where fd 2 points , then redirect fd 2
$ ls -l /proc/self/fd/  3>&2  2> /dev/null
total 0
lrwx------ 1 user user 64 Sep 13 00:08 0 -> /dev/pts/0
lrwx------ 1 user user 64 Sep 13 00:08 1 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:08 2 -> /dev/null
lrwx------ 1 runner user 64 Sep 13 00:08 3 -> /dev/pts/0
lr-x------ 1 user user 64 Sep 13 00:08 4 -> /proc/29/fd

# redirect fd #2 first, then clone it
$ ls -l /proc/self/fd/    2> /dev/null 3>&2
total 0
lrwx------ 1 user user 64 Sep 13 00:08 0 -> /dev/pts/0
lrwx------ 1 user user 64 Sep 13 00:08 1 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:08 2 -> /dev/null
l-wx------ 1 user user 64 Sep 13 00:08 3 -> /dev/null
lr-x------ 1 user user 64 Sep 13 00:08 4 -> /proc/31/fd

L'uso pratico di questi script in shell può essere versatile:

e molti altri.

Plumbing con pipe() e dup2()

Quindi, come vengono creati i tubi? attraverso pipe() syscall, che prenderà come input un array (aka lista) chiamato pipefd di due elementi di tipo int (numero intero). Questi due numeri interi sono descrittori di file. Il pipefd[0] sarà la parte letta del tubo e pipefd[1] sarà la fine della scrittura. Così dentro df | grep 'foo', grep otterrà una copia di pipefd[0] e df otterrà una copia di pipefd[1]. Ma come ? Certo, con la magia di dup2() syscall. Per df nel nostro esempio, diciamo pipefd[1] ha # 4, quindi il guscio farà un bambino, fallo dup2(4,1) (ricorda il mio cp esempio?), e poi fare execve() per funzionare davvero df. Naturalmente, df erediterà il descrittore di file n. 1, ma non saprà che non sta più puntando al terminale, ma in realtà fd # 4, che in realtà è la fine della scrittura della pipe. Naturalmente, la stessa cosa accadrà con grep 'foo' tranne con diversi numeri di descrittori di file.

Ora, domanda interessante: potremmo fare pipe che reindirizzano fd # 2, non solo fd # 1? Sì, in effetti è questo |&fa in bash. Lo standard POSIX richiede il linguaggio di comando della shell da supportare df 2>&1 | grep 'foo' sintassi per quello scopo, ma bash fa |& anche.

Ciò che è importante notare è che le pipe hanno sempre a che fare con i descrittori di file. Lì esiste FIFO o named pipe, che ha un nome file su disco e lo usiamo come file, ma si comporta come una pipe. Ma il | i tipi di pipe sono conosciuti come pipe anonimi - non hanno un nome file, perché in realtà sono solo due oggetti collegati tra loro. Il fatto che non abbiamo a che fare con i file ha anche un'importante implicazione: i tubi non lo sono lseek()'In grado. I file, sia in memoria che su disco, sono statici: i programmi possono essere utilizzati lseek() syscall per saltare al byte 120, quindi tornare al byte 10, quindi inoltrare fino alla fine. I pipe non sono statici, sono sequenziali e quindi non è possibile riavvolgere i dati con cui li si riceve lseek(). Questo è ciò che rende consapevoli alcuni programmi se stanno leggendo da file o da pipe, e quindi possono apportare le necessarie modifiche per prestazioni efficienti; in altre parole, a prog in grado di rilevare se lo faccio cat file.txt | prog o prog < input.txt. Un esempio di lavoro reale coda.

Le altre due proprietà molto interessanti di pipe sono che hanno un buffer, che su Linux è 4096 bytee in realtà hanno un filesystem come definito nel codice sorgente di Linux ! Non sono semplicemente un oggetto per il passaggio dei dati, sono essi stessi una struttura dati! Infatti, poiché esiste un filesystem pipefs, che gestisce sia le pipe che i FIFO, i tubi hanno un inode numero sul loro rispettivo filesystem:

# Stdout of ls is wired to pipe
$ ls -l /proc/self/fd/  | cat  
lrwx------ 1 user user 64 Sep 13 00:02 0 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:02 1 -> pipe:[15655630]
lrwx------ 1 user user 64 Sep 13 00:02 2 -> /dev/pts/0
lr-x------ 1 user user 64 Sep 13 00:02 3 -> /proc/22/fd
# stdin of ls is wired to pipe
$ true | ls -l /proc/self/fd/0
lr-x------ 1 user user 64 Sep 13 03:58 /proc/self/fd/0 -> 'pipe:[54741]'

Sui pipe Linux sono unidirezionali, proprio come il reindirizzamento. Su alcune implementazioni di tipo Unix, esistono pipe bidirezionali. Anche se con la magia dello scripting di shell, puoi farlo pipe bidirezionali su Linux anche.

Guarda anche:


2
2017-09-12 09:26





Ho riscontrato un problema con questo in C oggi. Essenzialmente, Pipe ha una semantica diversa da reindirizzare, anche se inviata a stdin. Davvero penso che date le differenze, le pipe dovrebbero andare da qualche altra parte stdin, così che stdin e lascia chiamarlo stdpipe (per fare un differenziale arbitrario) può essere gestito in diversi modi.

Considera questo. Quando si collega un output di un programma a un altro fstat sembra tornare zero come il st_size nonostante ls -lha /proc/{PID}/fd mostrando che c'è un file. Quando si reindirizza un file questo non è il caso (almeno su Debian wheezy, stretch e jessie vaniglia e ubuntu 14.04, 16.04vaniglia.

Se tu cat /proc/{PID}/fd/0 con un reindirizzamento potrai ripetere la lettura tutte le volte che vuoi. Se si esegue questa operazione con una pipe, si noterà che la seconda volta che si esegue l'operazione in modo consecutivo, non si ottiene lo stesso risultato.


1
2017-10-26 16:17