Pourquoi ne puis-je pas lire / dev / stdout avec un éditeur de texte?

9

Je viens de commencer à apprendre comment Everything Is A File TM sur Linux, ce qui m'a fait me demander ce qui se passerait si je lisais littéralement depuis / dev / stdout:

$ cat /dev/stdout 
^C
$ tail /dev/stdout 
^C

(C'est ^Cmoi qui tue le programme après qu'il se soit bloqué).

Lorsque j'essaye vim, j'obtiens le message impensable: "/ dev / stdout" n'est pas un fichier. Haleter!

Alors qu'est-ce qui donne, pourquoi est-ce que j'obtiens des blocages ou des messages d'erreur quand j'essaye de lire ces "fichiers"?

user1717828
la source
1
Ce que vim considère comme un fichier et ce que signifie "tout est un fichier" (pas de marque associée) dans * nix ne sont pas la même chose. Voir par exemple # 1 et # 2 .
goldilocks

Réponses:

11

pourquoi ai-je des raccords

Vous n'obtenez pas de "raccrochages" cat(1)et tail(1)ils bloquent simplement la lecture. cat(1)attend l'entrée et l'imprime dès qu'il voit une ligne complète:

$ cat /dev/stdout
foo
foo
bar
bar

Ici, j'ai tapé fooEnterbarEnterCTRL- D.

tail(1)attend l'entrée et l'imprime uniquement lorsqu'il peut détecter EOF:

$ tail /dev/stdout
foo
bar
foo
bar

Ici, j'ai tapé à nouveau fooEnterbarEnterCTRL- D.

ou des messages d'erreur

Vim est le seul qui vous donne une erreur. Il fait cela parce qu'il est stat(2) contre /dev/stdout, et il trouve que le S_IFREGbit n'est pas défini.

/dev/stdoutest un fichier, mais pas un fichier normal . En fait, il y a de la danse dans le noyau pour lui donner une entrée dans le système de fichiers. Sous Linux:

$ ls -l /dev/stdout
lrwxrwxrwx 1 root root 15 May  8 19:42 /dev/stdout -> /proc/self/fd/1

Sur OpenBSD:

$ ls -l /dev/stdout
crw-rw-rw-  1 root  wheel   22,   1 May  7 09:05:03 2015 /dev/stdout

Sur FreeBSD:

$ ls -l /dev/stdout
lrwxr-xr-x  1 root  wheel  4 May  8 21:35 /dev/stdout -> fd/1

$ ls -l /dev/fd/1
crw-rw-rw-  1 root  wheel  0x18 May  8 21:35 /dev/fd/1
lcd047
la source
5

(Presque) tout est un fichier mais tout n'est pas un fichier normal . Cela n'a pas de sens d'appeler un éditeur de texte sur quelque chose qui est un fichier spécial tel qu'un répertoire, une prise réseau, un port série, etc.

Le fichier /dev/stdoutpeut être une ou plusieurs choses selon la variante unix:

  • un fichier «spécial», généralement un périphérique de caractères;
  • un lien symbolique «magique» qui pointe vers le fichier que le processus y accédant a ouvert sur ce descripteur;
  • un lien symbolique vers l'un des éléments ci-dessus.

Dans tous les cas, l'ouverture de /dev/stdoutfichiers similaires crée un nouveau descripteur de fichier associé au même fichier que l'application a déjà ouvert sur le descripteur de fichier 1. «Sortie standard» signifie le descripteur de fichier 1, et c'est seulement une convention que ce descripteur de fichier est utilisé pour la sortie - le noyau s'en fiche.

Lorsque vous exécutez un programme dans un terminal, les trois descripteurs standard (0 = entrée standard, 1 = sortie standard, 2 = erreur standard) sont ouverts sur le terminal. La lecture à partir de ce périphérique renvoie des caractères saisis par l'utilisateur et l'écriture sur ce périphérique affiche du texte dans la fenêtre du terminal. (Il n'existe aucun moyen standard, étant donné un périphérique terminal, de lire la sortie qu'il affiche ou d'y injecter une entrée.)

Lorsque vous exécutez cat /dev/stdout, cela fait exactement la même chose que cat /dev/stdinor cat /dev/stderr, car ces trois descripteurs de fichiers sont connectés au même fichier: il indique catde lire à partir du terminal. C'est ce catque fait sans argument aussi.

Si vous couriez cat /dev/stdout >foo, alors vous vous /dev/stdoutréférez au fichier foo- cette commande est équivalente à cat foo >foo. En fonction de l' catimplémentation, il peut soit sortir une erreur (la version GNU se plaint que «le fichier d'entrée est un fichier de sortie»), soit ne rien faire car il lit le fichier foovide ( >foojuste tronqué). Avec une version catqui ne détecte pas ce cas spécial, si foon'est pas vide, alors cat /dev/stdout >>fooou l'équivalent cat foo >>fooajouterait le contenu du fichier à lui-même indéfiniment.

Lorsque vous exécutez vim /dev/stdout, il se plaint car il ne sait pas comment éditer un terminal (cela n'a tout simplement pas de sens).

Gilles 'SO- arrête d'être méchant'
la source
2

catet tailrecherchent un contenu facultatif suivi d'une fin de fichier. /dev/stdoutreste ouvert, donc catet tailjuste continuer à chercher.

Politank-Z
la source