Pourquoi ne puis-je pas `tail -f / proc / $ pid / fd / 1`?


10

J'ai écrit un script simple qui echo-es son PID:

#/bin/bash

while true; do
    echo $$;
    sleep 0.5;
done

J'exécute ledit script (il dit 3844encore et encore) dans un terminal et j'essaie taille descripteur de fichier dans un autre:

$ tail -f /proc/3844/fd/1

Il n'imprime rien à l'écran et se bloque jusqu'à ^c. Pourquoi?

De plus, tous les descripteurs de fichiers STD (IN / OUT / ERR) sont liés aux mêmes points:

$ ls -l /proc/3844/fd/
total 0
lrwx------ 1 mg mg 64 sie 29 13:42 0 -> /dev/pts/14
lrwx------ 1 mg mg 64 sie 29 13:42 1 -> /dev/pts/14
lrwx------ 1 mg mg 64 sie 29 13:42 2 -> /dev/pts/14
lr-x------ 1 mg mg 64 sie 29 13:42 254 -> /home/user/test.sh
lrwx------ 1 mg mg 64 sie 29 13:42 255 -> /dev/pts/14

Est-ce normal?

Exécuter Ubuntu GNOME 14.04.

Si vous pensez que cette question appartient à SO ou SU au lieu d'UL, dites-le.


Réponses:


13

Faire un stracede tail -f, il explique tout. La partie intéressante:

13791 fstat(3, {st_mode=S_IFREG|0644, st_size=139, ...}) = 0
13791 fstatfs(3, {...}) = 0
13791 inotify_init()                    = 4
13791 inotify_add_watch(4, "/path/to/file", IN_MODIFY|IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF) = 1
13791 fstat(3, {st_mode=S_IFREG|0644, st_size=139, ...}) = 0
13791 read(4, 0xd981c0, 26)             = -1 EINTR (Interrupted system call)

Ce qu'il fait? Il configure un inotifygestionnaire du fichier, puis attend que quelque chose se produise avec ce fichier. Si le noyau dit à tailtravers ce gestionnaire inotify, que le fichier a changé (normalement, a été ajouté), alors tail1) cherche 2) lit les modifications 3) les écrit à l'écran.

/proc/3844/fd/1sur votre système est un lien symbolique vers /dev/pts/14, qui est un périphérique de caractères. Il n'y a rien de tel que certains comme une "carte mémoire", qui pourrait être accessible par cela. Ainsi, il n'y a rien dont les modifications pourraient être signées dans l'inotify, car il n'y a pas de zone de disque ou de mémoire accessible par cela.

Ce périphérique de caractères est un terminal virtuel, qui fonctionne pratiquement comme s'il s'agissait d'une prise réseau. Les programmes exécutés sur ce terminal virtuel se connectent à cet appareil (comme si vous vous connectiez telnet à un port tcp) et écrivent dans quoi ils veulent écrire. Il y a aussi des choses plus complexes, par exemple le verrouillage de l'écran, les séquences de contrôle de terminal et autres, celles-ci sont normalement gérées par des ioctl()appels.

Je pense que vous voulez en quelque sorte regarder un terminal virtuel. Cela peut être fait sur linux, mais ce n'est pas si simple, il a besoin de certaines fonctionnalités de type proxy réseau et d'un peu d'utilisation délicate de ces ioctl()appels. Mais il existe des outils qui peuvent le faire.

Actuellement, je ne me souviens pas quel paquet Debian a l'outil pour atteindre cet objectif, mais avec un peu de recherche sur Google, vous pourrez probablement le trouver facilement.

Extension: comme @Jajesh l'a mentionné ici (donnez-lui un +1 si vous me l'avez donné), l'outil est nommé watch.

Extension # 2: @kelnos a mentionné, un simple cat /dev/pts/14était également suffisant. J'ai essayé cela, et oui, cela a fonctionné, mais pas correctement. Je n'ai pas beaucoup expérimenté avec cela, mais il me semble que si une sortie entrant dans ce terminal virtuel est allée soit à la catcommande, soit à son emplacement d'origine, et jamais aux deux. Mais ce n'est pas sûr.


La réponse de Peterh about tailest correcte (le bit de veille inotify), mais il est incorrect en ce qu'il est en fait très simple de faire ce que vous voulez: utilisez simplement à la catplace de tail.
kelnos

@kelnos Merci, je vais essayer et étendre ma réponse avec les résultats.
peterh

@kelnos catne fonctionne pas non plus pour moi, il se bloque de la même manière que la queue et tout ce que je peux faire est de le faire ctrl+c.
cprn

1
Je ne comprends toujours pas. J'ai changé echo $$pour echo $$ >> foomaintenant il y a un fichier et le processus l'ouvre et l'ajoute toutes les 0,5 secondes. Je ne peux toujours pas y accéder via le descripteur de fichier et tous les descripteurs de fichiers /proc/$pid/fd/(mais 254 qui sont liés au test.shscript lui-même) sont liés /dev/pts/14. Comment bash y accède-t- fooil?
cprn

1
étrange, il ne semble fonctionner que dans certaines situations. en utilisant le script de la question, cela ne fonctionne pas. mais si je fais "echo $$" dans un shell, puis cat FD 1 sur ce pid dans un autre shell, tout ce que je tape dans le premier shell est répercuté dans le second.
kelnos

4

Les fichiers dans /dev/ptsne sont pas des fichiers normaux, ce sont des poignées pour les terminaux virtuels. Un ptscomportement de lecture et d'écriture n'est pas symétrique (c'est-à-dire que ce qui y est écrit peut être lu ultérieurement, comme un fichier normal ou un fifo / pipe), mais médiatisé par le processus qui a créé le terminal virtuel: certains courants sont xterm ou ssh ou agetty ou screen. Le processus de contrôle enverra généralement des pressions de touches aux processus qui lisent le ptsfichier et rendra à l'écran ce qu'ils écrivent sur le pts.

Ainsi, tail -f /dev/pts/14imprimera les touches que vous appuyez sur le terminal à partir duquel vous avez commencé votre script, et si vous le faites, echo meh > /dev/pts/14le mehmessage apparaîtra dans le terminal.


Vous avez raison de dire que je peux écrire sur l'appareil pts mais je n'arrive pas à lire à partir de celui-ci. Comme dans: tail -f /dev/pts/14n'imprime pas les touches que je tape sur ce terminal. C'est une réponse intéressante, cependant. Merci.
cprn

0

Il y a quelque temps j'ai trouvé un peu contournement qui parfois répond à la nécessité de vérifier ce qui est à STDOUT émis, supposant que vous avez un piddu processus et vous pouvez nu les yeux résultats hostiles:

sudo strace -p $pid 2>&1 | grep write\(

-2

Je suppose que pour cela plutôt que de suivre, ce que vous devez faire serait de regarder la sortie.

$ watch -n2 ls -l /proc/3844/fd/

J'espère que c'est ce dont vous avez besoin.


3
Cette commande affichera la liste des fds ouverts toutes les 2 secondes, pas la sortie de contenu sur stdout.
Ángel

Angel, c'est vrai. Il pourrait utiliser la montre avec un chat pour voir le résultat sur quel descripteur il veut surveiller. Je suppose que @ peter-horvath, a donné l'explication parfaite de la question.
Jayesh

Je sais watch. Ce que j'essaie de faire est de jeter un œil à la sortie du processus déjà en cours, donc watchça n'aide pas.
cprn
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.