Perché non posso `tail -f / proc / $ pid / fd / 1`?


10

Ho scritto un semplice script che è il echosuo PID:

#/bin/bash

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

Sto eseguendo detto script (dice 3844ripetutamente) in un terminale e provando tailil descrittore di file in un altro:

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

Non stampa nulla sullo schermo e si blocca fino a quando ^c. Perché?

Inoltre, tutti i descrittori di file STD (IN / OUT / ERR) si collegano agli stessi punti:

$ 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

È normale?

Esecuzione di Ubuntu GNOME 14.04.

Se pensi che questa domanda appartenga a SO o SU invece di UL, dillo.


Risposte:


13

Fare un stracedi tail -f, si spiega tutto. La parte interessante:

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)

Cosa fa? Imposta un inotifygestore per il file e quindi attende che accada qualcosa con questo file. Se il kernel dice tailattraverso questo gestore inotify, che il file è cambiato (normalmente, è stato aggiunto), allora tail1) cerca 2) legge le modifiche 3) le scrive sullo schermo.

/proc/3844/fd/1sul tuo sistema c'è un collegamento simbolico a /dev/pts/14, che è un dispositivo personaggio. Non esiste qualcosa come una "mappa di memoria", alla quale si può accedere. Pertanto, non esiste nulla le cui modifiche possano essere firmate per inotify, poiché non vi è alcuna area su disco o memoria a cui si possa accedere.

Questo dispositivo personaggio è un terminale virtuale, che funziona praticamente come se fosse un socket di rete. I programmi in esecuzione su questo terminale virtuale si stanno connettendo a questo dispositivo (proprio come se si fosse telnetizzato in una porta tcp) e scrivessero ciò che vogliono scrivere. Ci sono anche cose più complesse, ad esempio il blocco dello schermo, le sequenze di controllo dei terminali e simili, che normalmente vengono gestite dalle ioctl()chiamate.

Penso che tu voglia in qualche modo guardare un terminale virtuale. Può essere fatto su Linux, ma non è così semplice, ha bisogno di alcune funzionalità di tipo proxy di rete e un po 'di uso complicato di queste ioctl()chiamate. Ma ci sono strumenti che possono farlo.

Al momento non ricordo, quale pacchetto debian ha lo strumento per questo obiettivo, ma con un po 'di googling potresti trovarlo probabilmente facilmente.

Estensione: come menzionato qui @Jajesh (dagli un +1 se mi hai dato), lo strumento è chiamato watch.

Estensione n. 2: @kelnos menzionato, cat /dev/pts/14bastava anche un semplice . Ci ho provato, e sì, ha funzionato, ma non correttamente. Non l'ho sperimentato molto, ma mi sembra che un'uscita in quel terminale virtuale sia andata al catcomando, o alla sua posizione originale, e mai ad entrambi. Ma non è sicuro.


la risposta di peterh tailè corretta (il bit di inotify watch), ma non è corretto in quanto è in realtà molto semplice fare quello che vuoi: basta usare catinvece di tail.
kelnos,

@kelnos Grazie, ci proverò ed estenderò la mia risposta con i risultati.
Peter - Ripristina Monica il

@kelnos catnon funziona neanche per me, si blocca allo stesso modo della coda e tutto quello che posso fare è farlo ctrl+c.
cprn,

1
Ancora non capisco. Sono passato echo $$a echo $$ >> foocosì ora c'è un file e il processo lo apre e lo aggiunge ogni 0,5 secondi. Non riesco ancora ad accedervi tramite il descrittore di file e tutti i descrittori di file in /proc/$pid/fd/(ma 254 che si collega allo test.shscript stesso) al link /dev/pts/14. Come accede Bash a foocui scrive?
cprn,

1
strano, sembra funzionare solo in alcune situazioni. usando lo script nella domanda, non funziona. ma se faccio "echo $$" in una shell, e quindi cat FD 1 su quel pid in un'altra shell, tutto ciò che scrivo nella prima shell viene ripetuto nella seconda.
kelnos,

4

I file in /dev/ptsnon sono file regolari, sono handle per terminali virtuali. Un ptscomportamento per la lettura e la scrittura non è simmetrico (ovvero, ciò che è scritto in esso può essere successivamente letto da esso, come un file normale o un fifo / pipe), ma mediato dal processo che ha creato il terminale virtuale: alcuni comuni sono xterm o ssh o agetty o screen. Il processo di controllo generalmente invia i tasti premuti ai processi che leggono il ptsfile e rende sullo schermo ciò che scrivono pts.

Quindi, tail -f /dev/pts/14stamperà i tasti che tocchi sul terminale da cui hai iniziato lo script, e se lo fai echo meh > /dev/pts/14il mehmessaggio apparirà nel terminale.


Hai ragione a dire che posso scrivere sul dispositivo pts ma non riesco a leggere da esso. Come in: tail -f /dev/pts/14non stampa i tasti che tocco su quel terminale. È una risposta interessante, però. Grazie.
cprn,

0

Qualche tempo fa ho trovato una sorta di soluzione alternativa che a volte risponde alla necessità di verificare ciò che viene emesso a STDOUT, supponendo che tu abbia un pidprocesso e che tu possa scoprire gli occhi in modo ostile:

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

-2

Immagino, per questo piuttosto che per la coda, quello che devi fare sarebbe guardare l'output.

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

Spero che questo sia ciò di cui hai bisogno.


3
Questo comando mostrerà l'elenco dei file fds aperti ogni 2 secondi, non l' output del contenuto su stdout.
Ángel,

Angelo, vero. Potrebbe usare l'orologio con un gatto per vedere il risultato su quale descrittore desidera monitorare. Immagino che @ peter-horvath abbia dato la spiegazione perfetta per la domanda.
Jayesh,

Lo so watch. Quello che sto cercando di fare è sbirciare l'output del processo già in esecuzione, quindi watchnon aiuta.
cprn,
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.