Question Quelle est la différence entre “Redirection” et “Pipe”?


Cette question peut sembler un peu stupide, mais je ne peux pas vraiment voir la différence entre redirection et tuyaux.

La redirection est utilisée pour rediriger le stdout / stdin / stderr, par ex. ls > log.txt.

Les tuyaux sont utilisés pour donner la sortie d'une commande en entrée d'une autre commande, par ex. ls | grep file.txt.

Mais pourquoi y a-t-il deux opérateurs pour la même chose?

Pourquoi ne pas simplement écrire ls > grep passer la sortie à travers, n'est-ce pas simplement une sorte de redirection? Ce qui me manque


173
2017-08-07 13:22


origine




Réponses:


Le tuyau est utilisé pour transmettre la sortie à un autre programme ou utilitaire.

La redirection est utilisée pour transmettre la sortie à un fichier ou flux.

Exemple: thing1 > thing2 contre thing1 | thing2

thing1 > thing2

  1. Votre shell exécutera le programme nommé thing1
  2. Tout ce que thing1 les sorties seront placées dans un fichier appelé thing2. (Remarque - si thing2 existe, il sera écrasé)

Si vous voulez passer la sortie du programme thing1 à un programme appelé thing2, vous pouvez faire ce qui suit:

thing1 > temp_file && thing2 < temp_file

qui ferait

  1. exécuter le programme nommé thing1
  2. enregistrer la sortie dans un fichier nommé temp_file
  3. exécuter le programme nommé thing2, prétendant que la personne au clavier a tapé le contenu de temp_file comme entrée.

Cependant, c'est maladroit, donc ils ont fait des tuyaux comme un moyen plus simple de le faire. thing1 | thing2 fait la même chose que thing1 > temp_file && thing2 < temp_file

EDIT pour fournir plus de détails à remettre en question dans un commentaire:

Si > essayé d'être à la fois "pass to program" et "write to file", cela pourrait causer des problèmes dans les deux sens.

Premier exemple: Vous essayez d'écrire dans un fichier. Il existe déjà un fichier avec ce nom que vous souhaitez écraser. Cependant, le fichier est exécutable. Vraisemblablement, il essaierait d'exécuter ce fichier, en passant l'entrée. Vous devez faire quelque chose comme écrire la sortie sur un nouveau nom de fichier, puis renommer le fichier.

Deuxième exemple: Comme Florian Diesch l'a souligné, s'il y a une autre commande ailleurs dans le système avec le même nom (c'est-à-dire dans le chemin d'exécution). Si vous vouliez créer un fichier portant ce nom dans votre dossier actuel, vous seriez bloqué.

Troisièmement: Si vous tapez une commande à tort, cela ne vous avertira pas que la commande n'existe pas. En ce moment, si vous tapez ls | gerp log.txt ça vous dira bash: gerp: command not found. Si > signifiait à la fois, cela créerait simplement un nouveau fichier pour vous (puis avertir qu'il ne sait pas quoi faire avec log.txt).


194
2017-08-07 13:30



Je vous remercie. Vous avez mentionné thing1 > temp_file && thing2 < temp_file faire plus facilement avec les tuyaux. Mais pourquoi ne pas réutiliser le > opérateur pour le faire, par ex. thing1 > thing2 pour les commandes thing1 et thing2 ? Pourquoi un opérateur supplémentaire | ? - John Threepwood
"Prendre la sortie et l'écrire dans un fichier" est une action différente de "Prendre la sortie et la transmettre à un autre programme". Je vais éditer plus de pensées dans ma réponse ... - David Oneill
@JohnThreepwood Ils ont des significations différentes. Et si je voulais rediriger quelque chose vers un fichier nommé less, par exemple? thing | less et thing > less sont parfaitement différents, car ils font des choses différentes. Ce que vous proposez créerait une ambiguïté. - Darkhogg
Est-il exact de dire que "thing1> temp_file" est simplement du sucre syntaxique pour "thing1 | tee temp_file"? Depuis que j'ai découvert le tee, je n'utilise presque jamais de redirections. - Sridhar-Sarnobat
@ Sridhar-Sarnobat non, le tee commande fait quelque chose de différent. tee écrit la sortie à la fois sur l'écran (stdout) et le fichier. Redirect seulement le fichier. - David Oneill


Si le sens de foo > bar dépendrait s'il y a une commande nommée bar cela rendrait l'utilisation de la redirection beaucoup plus difficile et plus sujette aux erreurs: chaque fois que je voulais rediriger vers un fichier, je devais d'abord vérifier s'il y avait une commande nommée comme mon fichier de destination.


19
2017-08-07 13:40



Ce ne serait un problème que si vous écrivez à bar dans un répertoire qui fait partie de votre $PATH variable env. Si vous êtes dans quelque chose comme / bin, cela pourrait poser problème. Mais même alors, bar devrait avoir un ensemble d'autorisations exécutables, de sorte que le shell vérifie non seulement pour trouver un exécutable bar mais peut réellement l'exécuter. Et si le souci est de remplacer le fichier existant, noclober L’option shell devrait empêcher l’écrasement des fichiers existants dans les redirections. - Sergiy Kolodyazhnyy


Il y a une différence essentielle entre les deux opérateurs:

  1. ls > log.txt -> Cette commande envoie la sortie au fichier log.txt.

  2. ls | grep file.txt -> Cette commande envoie la sortie de la commande ls à grep via l'utilisation de pipe (|), et la commande grep recherche fichier.txt dans l’entrée fournie par la commande précédente.

Si vous deviez effectuer la même tâche en utilisant le premier scénario, ce serait alors:

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

Donc une pipe (avec |) est utilisé pour envoyer la sortie à une autre commande, alors que la redirection (avec >) est utilisé pour rediriger la sortie vers un fichier.


11
2017-08-07 13:32





A partir du manuel d'administration système Unix et Linux:

Redirection

Le shell interprète les symboles <,> et >> comme des instructions pour réacheminer un commande entrée ou sortie vers ou depuis un fichier.

Pipes

Pour connecter le STDOUT d'un commander au STDIN de un autre utiliser le | symbole, communément appelé un tuyau.

Donc, mon interprétation est la suivante: si c'est la commande à commander, utilisez un tuyau. Si vous exportez vers ou depuis un fichier, utilisez la redirection.


9
2018-02-16 00:40





Il y a une grande différence syntaxique entre les deux:

  1. Une redirection est un argument pour un programme
  2. Un tuyau sépare deux commandes

Vous pouvez penser à des redirections comme celle-ci: cat [<infile] [>outfile]. Cela implique que l'ordre n'a pas d'importance: cat <infile >outfile est le même que cat >outfile <infile. Vous pouvez même mélanger des redirections avec d'autres arguments: cat >outfile <infile -b et cat <infile -b >outfile sont tous deux parfaitement bien. Vous pouvez également enchaîner plusieurs entrées ou sorties (les entrées seront lues séquentiellement et toutes les sorties seront écrites dans chaque fichier de sortie): cat >outfile1 >outfile2 <infile1 <infile2. La cible ou la source d'une redirection peut être un nom de fichier ou le nom d'un flux (comme & 1, au moins en bash).

Mais les tuyaux séparent totalement une commande d'une autre commande, vous ne pouvez pas les mélanger avec des arguments:

[command1] | [command2]

Le tube prend tout ce qui est écrit sur la sortie standard de la commande 1 et l'envoie à l'entrée standard de commande2.

Vous pouvez également combiner la tuyauterie et la redirection. Par exemple:

cat <infile >outfile | cat <infile2 >outfile2

La première cat lit les lignes de l’infile, puis écrit simultanément chaque ligne dans le fichier et l’envoie au second cat.

Dans la seconde cat, l'entrée standard lit d'abord le tube (le contenu de l'infile), puis lit à partir de infile2, écrivant chaque ligne dans le fichier2. Après avoir exécuté ceci, outfile sera une copie de infile et outfile2 contiendra infile suivi de infile2.

Enfin, vous faites réellement quelque chose de très similaire à votre exemple en utilisant la redirection "here string" (famille bash uniquement) et les backticks:

grep blah <<<`ls`

donnera le même résultat que

ls | grep blah

Mais je pense que la version de redirection lira d'abord toute la sortie de ls dans un tampon (en mémoire), puis alimentera ce tampon en une seule ligne à la fois, alors que la version en ligne prendra chaque ligne à partir de ls, et passez cette ligne à grep.


3
2017-08-23 22:24



Nitpick: l'ordre compte dans la redirection si vous redirigez un fd vers un autre: echo yes 1>&2 2>/tmp/blah; wc -l /tmp/blah; echo yes 2>/tmp/blah 1>&2; wc -l /tmp/blah De plus, la redirection vers un fichier utilisera uniquement la dernière redirection. echo yes >/tmp/blah >/tmp/blah2 n'écrira qu'à /tmp/blah2. - muru
Redirect n'est pas en fait un argument pour le programme. Le programme ne saura pas ou ne se souciera pas de la destination de sa sortie (ou de l’entrée provient). C'est juste une façon de dire à bash comment organiser les choses avant d'exécuter le programme. - Alois Mahdal


Pour ajouter aux autres réponses, il existe également une différence sémantique subtile - par ex. les tuyaux se ferment plus facilement que les redirections:

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

Dans le premier exemple, lorsque le premier appel à head se termine, il ferme le tuyau, et seq se termine, donc il n'y a pas d'entrée disponible pour le second head.

Dans le deuxième exemple, la tête consomme la première ligne, mais quand elle se ferme elle-même stdin  tuyau, le fichier reste ouvert pour le prochain appel à utiliser.

Le troisième exemple montre que si nous utilisons read pour éviter de fermer le tuyau, il est toujours disponible dans le sous-processus.

Donc, le "flux" est la chose par laquelle nous shuntons les données (stdin, etc.), et est le même dans les deux cas, mais le canal connecte les flux de deux processus, où une redirection connecte un flux entre un processus et un fichier. peut voir la source des similitudes et des différences.

P.S. Si vous êtes aussi curieux et / ou surpris par ces exemples que par le passé, vous pouvez aller plus loin en utilisant trap pour voir comment les processus résolvent, par exemple:

(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))

Parfois, le premier processus se ferme avant 1 est imprimé, parfois après.

Je l'ai également trouvé intéressant à utiliser exec <&- fermer le flux de la redirection pour se rapprocher du comportement du canal (avec une erreur):

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



"Lorsque le premier appel à la tête se termine, il ferme le tuyau" Ceci est en réalité inexact pour deux raisons. L'un (head -n1; head -n1) est un sous-shell avec deux commandes dont chacune hérite de la fin du canal de lecture comme descripteur 0, et donc le sous-shell AND, chaque commande a ce descripteur de fichier ouvert. Deuxième raison, vous pouvez le voir avec strace -f bash -c 'seq 5 | (tête -n1; tête -n1) '. Donc, la première tête ferme seulement sa copie du descripteur de fichier - Sergiy Kolodyazhnyy
Le troisième exemple est également inexact, car read ne consomme que la première ligne (c'est un octet pour 1 et newline). seq envoyé au total 10 octets (5 numéros et 5 nouvelles lignes). Donc, il reste 8 octets dans le tampon de pipe, et c'est pourquoi la seconde head fonctionne - il y a encore des données disponibles dans le tampon de tuyau. Btw, la tête ne sort que s'il y a 0 octet lu, un peu comme dans head /dev/null - Sergiy Kolodyazhnyy
Merci pour la clarification. Est-ce que je comprends bien que dans seq 5 | (head -n1; head -n1)le premier appel vide le tuyau, donc il existe toujours dans un état ouvert mais sans données pour le deuxième appel à head? Ainsi, la différence de comportement entre le canal et la redirection est due au fait que la tête extrait toutes les données du canal, mais uniquement les 2 lignes du fichier? - Julian de Bhal
C'est correct. Et c'est quelque chose qui peut être vu avec strace commande que j'ai donné dans le premier commentaire. Avec la redirection, le fichier tmp se trouve sur le disque, ce qui le rend accessible (car ils utilisent lseek() syscall - les commandes peuvent contourner le fichier du premier octet pour durer comme elles le souhaitent. Mais les tuyaux sont séquentiels et non recherchables. Donc, la seule façon pour la tête de faire son travail est de tout lire en premier, ou si le fichier est volumineux - en attribuer une partie à la RAM via mmap() appel. Une fois j'ai fait le mien tail en Python, et a rencontré exactement le même problème. - Sergiy Kolodyazhnyy
Il est également important de se rappeler que la fin de lecture du tube (descripteur de fichier) est donnée en premier au sous-shell. (...), et le sous-shell fera une copie de son propre stdin à chaque commande à l'intérieur (...). Donc, ils sont techniquement lus à partir du même objet. Premier head  pense qu'il lit de sa propre stdin. Seconde head pense qu'il a son propre stdin. Mais en réalité leur fd # 1 (stdin) est juste une copie de la même fd, qui est la fin lue du tube. Aussi, j'ai posté une réponse, alors peut-être que ça va aider à clarifier les choses. - Sergiy Kolodyazhnyy


Note: La réponse reflète ma propre compréhension de ces mécanismes mis à jour, accumulés au fil de la recherche et de la lecture des réponses par les pairs sur ce site et unix.stackexchange.com, et sera mis à jour avec le temps. N'hésitez pas à poser des questions ou à suggérer des améliorations dans les commentaires. Je vous suggère également d’essayer de voir comment syscalls fonctionne en shell avec strace commander. Aussi, s'il vous plaît, ne soyez pas intimidé par la notion d'internals ou de syscalls - vous n'avez pas besoin de les connaître ou de les utiliser pour comprendre comment shell fait les choses, mais ils aident certainement à la compréhension.

TL; DR

  • | les tuyaux ne sont pas associés à une entrée sur le disque, donc ne pas avoir d'inode nombre de systèmes de fichiers disque (mais ont inode dans pipefs système de fichiers virtuel dans l'espace noyau), mais les redirections impliquent souvent des fichiers, qui ont des entrées de disque et ont donc l'inode correspondant.
  • les tuyaux ne sont pas lseek()'commandes donc capables ne peuvent pas lire certaines données et puis revenir en arrière, mais quand vous redirigez avec > ou < habituellement c'est un fichier qui est lseek() objet capable, donc les commandes peuvent naviguer comme bon leur semble.
  • les redirections sont des manipulations sur les descripteurs de fichiers, qui peuvent être nombreuses; les pipes n'ont que deux descripteurs de fichiers - un pour la commande de gauche et un pour la commande de droite
  • la redirection sur les flux et les canaux standard est mise en mémoire tampon.
  • les pipes impliquent presque toujours le forking, les redirections - pas toujours
  • Les pipes traitent toujours avec les descripteurs de fichiers, les redirections - utilisez des fichiers réels avec un nom de fichier sur le disque ou des descripteurs de fichiers.
  • les pipes sont une méthode de communication entre processus, alors que les redirections ne sont que des manipulations sur des fichiers ouverts ou des objets de type fichier
  • les deux emploient dup2() syscalls sous le capot pour fournir des copies des descripteurs de fichiers, où le flux de données réel se produit.
  • les redirections peuvent être appliquées "globalement" avec exec commande intégrée (voir ce et ce ), alors si vous le faites exec > output.txt chaque commande écrira à output.txt à partir de maintenant. | les tuyaux ne sont appliqués que pour la commande en cours (ce qui signifie soit une commande simple, soit un sous-shell comme seq 5 | (head -n1; head -n2)ou des commandes composées.
  • Lorsque la redirection est effectuée sur des fichiers, des choses comme echo "TEST" > file et echo "TEST" >> file les deux utilisent open() syscall sur ce fichier (voir également) et obtenir un descripteur de fichier pour le transmettre à dup2(). Pipes | Usage unique pipe() et dup2() syscall.

introduction

Afin de comprendre en quoi ces deux mécanismes diffèrent, il est nécessaire de comprendre leurs propriétés essentielles, l’historique de ces deux mécanismes et leurs racines dans le langage de programmation C. En fait, savoir quels sont les descripteurs de fichiers et comment dup2() et pipe() les appels système sont essentiels, de même que lseek(). Shell est un moyen de rendre ces mécanismes abstraits pour l'utilisateur, mais creuser plus profondément que l'abstraction permet de comprendre la véritable nature du comportement du shell.

Les origines des redirections et des tuyaux

Selon l’article de Dennis Ritche Pétroglyphes prophétiques, les tuyaux provenaient d'un Note interne de 1964 par Malcolm Douglas McIlroy, au moment où ils travaillaient sur Système d'exploitation Multics. Citation:

Pour résumer mes préoccupations les plus fortes:

  1. Nous devrions avoir des moyens de connecter des programmes comme un tuyau d'arrosage dans un autre segment lorsqu'il devient nécessaire de masser les données autrement. C'est la façon dont IO aussi.

Ce qui est évident, c'est qu'à l'époque les programmes étaient capables d'écrire sur le disque, mais cela était inefficace si la production était importante. Pour citer l'explication de Brian Kernighan dans Pipeline Unix vidéo :

Tout d'abord, vous n'avez pas besoin d'écrire un gros programme massif - vous avez déjà des programmes plus petits qui peuvent déjà faire partie du travail ... Une autre est qu'il est possible que la quantité de données que vous traitez ne convienne pas si vous l'avez stocké dans un fichier ... car rappelez-vous que nous étions de retour à l'époque où les disques portaient, si vous aviez de la chance, un ou deux mégaoctets de données ... Le pipeline n'a donc jamais eu à instancier l'intégralité de la sortie .

Ainsi, la différence conceptuelle est évidente: les pipes sont un mécanisme permettant aux programmes de se parler. Redirections - sont des moyens d'écrire dans un fichier de base. Dans les deux cas, l'obus rend ces deux choses faciles, mais sous le capot, il se passe beaucoup de choses.

Aller plus loin: appels systématiques et fonctionnement interne de la coque

Nous commençons par la notion de descripteur de fichier. Les descripteurs de fichiers décrivent essentiellement un fichier ouvert (que ce soit un fichier sur disque ou en mémoire, ou un fichier anonyme), représenté par un nombre entier. Les deux flux de données standard  (stdin, stdout, stderr) sont des descripteurs de fichiers 0,1 et 2 respectivement. D'où viennent-ils ? Eh bien, dans les commandes shell, les descripteurs de fichiers sont hérités de leur shell parent. Et c'est vrai en général pour tous les processus - le processus enfant hérite des descripteurs de fichier du parent. Pour démons il est courant de fermer tous les descripteurs de fichiers hérités et / ou de les rediriger vers d'autres endroits.

Retour à la redirection. Qu'est ce que c'est vraiment? C'est un mécanisme qui dit au shell de préparer des descripteurs de fichiers pour la commande (car les redirections sont effectuées par shell avant l'exécution de la commande), et leur indiquer où l'utilisateur a suggéré. le Définition standard de la redirection de sortie est

[n]>word

Cette [n] il y a le numéro du descripteur de fichier. Quand tu fais echo "Something" > /dev/null le numéro 1 y est implicite, et echo 2> /dev/null.

Sous le capot, cela se fait en dupliquant le descripteur de fichier via dup2() appel système. Prenons df > /dev/null. Le shell va créer un processus enfant où df fonctionne, mais avant cela, il va s'ouvrir /dev/null comme descripteur de fichier # 3, et dup2(3,1) sera émis, ce qui fait une copie du descripteur de fichier 3 et la copie sera 1. Vous savez comment vous avez deux fichiers file1.txt et file2.txtet quand vous le faites cp file1.txt file2.txt vous aurez deux fichiers identiques, mais vous pouvez les manipuler indépendamment? C'est un peu la même chose qui se passe ici. Souvent, vous pouvez voir que avant de courir, le bash ça ira dup(1,10) pour faire un descripteur de fichier n ° 1 qui est stdout (et cette copie sera fd # 10) afin de la restaurer plus tard. Important est de noter que lorsque vous considérez commandes intégrées (qui font partie du shell lui-même et n'ont pas de fichier dans /bin ou ailleurs) ou Commandes simples dans un shell non interactif, le shell ne crée pas de processus enfant.

Et puis nous avons des choses comme [n]>&[m] et [n]&<[m]. Ceci est la duplication des descripteurs de fichiers, dont le même mécanisme que dup2() seulement maintenant, il est dans la syntaxe du shell, disponible pour l'utilisateur.

Une des choses importantes à noter à propos de la redirection est que leur ordre n'est pas fixe, mais est important pour la façon dont le shell interprète ce que veut l'utilisateur. Comparez les éléments suivants:

# 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'utilisation pratique de ces scripts en shell peut être polyvalente:

et beaucoup d'autres.

Plomberie avec pipe() et dup2()

Alors, comment les pipes sont-elles créées? Via pipe() appel syscall, qui prendra en entrée un tableau (alias list) appelé pipefd de deux articles de type int (entier). Ces deux entiers sont des descripteurs de fichiers. le pipefd[0] sera la fin de lecture du tuyau et pipefd[1] sera la fin de l'écriture. Donc en df | grep 'foo', grep va obtenir une copie de pipefd[0] et df obtiendra une copie de pipefd[1]. Mais comment ? Bien sûr, avec la magie de dup2() syscall. Pour df dans notre exemple, disons pipefd[1] a # 4, donc le shell fera un enfant, faire dup2(4,1) (rappelez-vous mon cp exemple?), puis faire execve() pour courir réellement df. Naturellement, df héritera du descripteur de fichier n ° 1, mais ignorera qu'il ne pointe plus sur le terminal, mais sur fd # 4, qui correspond en fait à la fin de l'écriture du canal. Naturellement, la même chose se produira avec grep 'foo' sauf avec différents nombres de descripteurs de fichiers.

Maintenant, une question intéressante: pourrions-nous faire des tuyaux qui redirigent aussi le fd # 2, pas seulement le fd # 1? Oui, en fait c'est ça |&fait en bash. Le standard POSIX nécessite un langage de commande shell pour prendre en charge df 2>&1 | grep 'foo' syntaxe à cet effet, mais bash Est-ce que |& ainsi que.

Il est important de noter que les pipes traitent toujours avec les descripteurs de fichiers. Il existe FIFO ou pipe nommée, qui a un nom de fichier sur le disque et vous permet de l'utiliser comme un fichier, mais se comporte comme un tube. Mais le | Les types de tubes sont ce que l'on appelle les tubes anonymes - ils n'ont pas de nom de fichier, car ils ne sont en réalité que deux objets connectés ensemble. Le fait que nous ne travaillions pas avec des fichiers a également une implication importante: les tuyaux ne sont pas lseek()'capable. Les fichiers, en mémoire ou sur disque, sont statiques - les programmes peuvent utiliser lseek() syscall pour passer à l'octet 120, puis revenir à l'octet 10, puis avancer jusqu'à la fin. Les tuyaux ne sont pas statiques - ils sont séquentiels et, par conséquent, vous ne pouvez pas revenir en arrière avec les données que vous obtenez d’eux. lseek(). C'est ce qui permet à certains programmes de savoir s'ils lisent à partir d'un fichier ou à partir d'un canal, ce qui leur permet de faire les ajustements nécessaires pour optimiser les performances. en d'autres termes, un prog peut détecter si je fais cat file.txt | prog ou prog < input.txt. Exemple de travail réel de cela est queue.

L’autre propriété très intéressante des pipes est qu’elles ont un buffer qui sous Linux est de 4096 octets, et ils ont en fait un système de fichiers tel que défini dans le code source Linux ! Ils ne sont pas simplement un objet de transmission de données, ils constituent eux-mêmes une infrastructure de données! En fait, comme il existe un système de fichiers pipefs, qui gère à la fois les pipes et les FIFO, les tuyaux ont un inode nombre sur leur système de fichiers respectif:

# 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]'

Sur Linux, les tubes sont unidirectionnels, tout comme la redirection. Sur certaines implémentations de type Unix, il existe des canaux bidirectionnels. Bien qu'avec la magie des scripts shell, vous pouvez faire tuyaux bidirectionnels sous Linux ainsi que.

Voir également:


2
2017-09-12 09:26





J'ai rencontré un problème avec C aujourd'hui. Essentiellement, Pipe a une sémantique différente de celle des redirections, même si elles sont envoyées à stdin. Vraiment je pense compte tenu des différences, les tuyaux devraient aller ailleurs que stdin, pour que stdin et laisse l'appeler stdpipe (pour faire un différentiel arbitraire) peut être traité de différentes manières.

Considère ceci. Lors du raccordement d'un programme à un autre fstat semble revenir à zéro comme le st_size malgré ls -lha /proc/{PID}/fd montrant qu'il existe un fichier. Lorsque vous redirigez un fichier, ce n’est pas le cas (au moins sur debian wheezy, stretch et jessie vanille et ubuntu 14.04, 16.04vanille.

Si vous cat /proc/{PID}/fd/0 avec une redirection, vous pourrez répéter pour lire autant de fois que vous le souhaitez. Si vous faites cela avec un tube, vous remarquerez que la deuxième fois que vous exécutez la tâche consécutivement, vous ne recevez pas le même résultat.


1
2017-10-26 16:17