Neden kuyruk -f / proc / $ pid / fd / 1` yapamıyorum?


10

Ben echoonun PID -es basit bir komut dosyası yazdı :

#/bin/bash

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

Bahsedilen komut dosyasını 3844bir terminalde çalıştırıyorum ve tekrar tekrar söylüyorum ve tailbaşka bir dosya tanımlayıcısına çalışıyorum :

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

Ekrana hiçbir şey yazdırmaz ve sonrasına kadar askıda kalır ^c. Neden?

Ayrıca, tüm STD dosya tanımlayıcıları (IN / OUT / ERR) aynı puanlara bağlanır:

$ 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

Bu normal mi?

Ubuntu GNOME 14.04 çalışıyor.

Bu sorunun UL yerine SO veya SU'ya ait olduğunu düşünüyorsanız, söyleyin.


Yanıtlar:


13

Bir Make straceait tail -fher şeyi açıklıyor. İlginç kısım:

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)

Bu ne yapar? inotifyDosyaya bir işleyici kurar ve bu dosyada bir şey olana kadar bekler. Çekirdek tailbu inotify işleyici aracılığıyla dosyanın değiştiğini (normalde eklenmiş olduğunu) söylüyorsa , tail1) 2 arar) değişiklikleri okur 3) bunları ekrana yazar.

/proc/3844/fd/1sisteminizde /dev/pts/14, bir karakter cihazı olan simgesel bir bağlantıdır . Bazıları buna erişilebilen bir "hafıza haritası" gibi bir şey yoktur. Böylece, değişiklikleri inotify'a imzalayabilecek hiçbir şey yoktur, çünkü buna erişilebilecek disk veya bellek alanı yoktur.

Bu karakter cihazı, neredeyse bir ağ soketi gibi çalışan sanal bir terminaldir. Bu sanal terminalde çalışan programlar bu cihaza bağlanıyor (tıpkı bir tcp portuna telnet bağlamış gibi) ve yazmak istediklerini yazıyor. Ekranı kilitleme, terminal kontrol dizileri ve benzerleri gibi karmaşık şeyler de vardır, bunlar normalde ioctl()aramalarla ele alınır .

Sanırım, bir şekilde sanal bir terminal izlemek istiyorsunuz. Linux üzerinde yapılabilir, ancak o kadar basit değil, bazı ağ proxy'si gibi işlevlere ve bu ioctl()çağrıların biraz zor kullanımına ihtiyaç duyuyor . Ama bunu yapabilecek araçlar var.

Şu anda hatırlayamıyorum, hangi debian paketinin bu hedef için bir aracı var, ancak biraz googling ile bunu kolayca bulabilirsiniz.

Eklenti: @Jajesh burada belirtildiği gibi (bana verdiyseniz ona +1 verin), araç adlandırılır watch.

Uzantı 2: @kelnos, basit bir cat /dev/pts/14de yeterliydi. Bunu denedim ve evet, işe yaradı, ama doğru değil. Ben buna çok tecrübe yoktu, ama bir çıkış gitmiş o sanal terminale girmeden sanki bana öyle geliyor ya kadar catkomuta veya özgün konumuna ve asla hem. Ama emin değilim.


peterh'in cevabı taildoğrudur ( inotify saat biti), ama aslında istediğinizi yapmanın çok basit olması yanlış : sadece catyerine kullanın tail.
kelnos

@kelnos Teşekkürler, bunu deneyeceğim ve sonuçlarla cevabımı uzatacağım.
peterh - Monica'yı geri döndür

@kelnos catbenim için de çalışmıyor, kuyruğun yaptığı gibi duruyor ve yapabileceğim tek şey yapmak ctrl+c.
cprn

1
Hala anlamıyorum. Değiştim echo $$için echo $$ >> fooyani şimdi orada bir dosya var ve süreç her 0.5 saniyede bir bunu açar ve buna ekler. Hala dosya tanımlayıcı ve tüm dosya tanımlayıcıları /proc/$pid/fd/(ancak test.shkomut dosyasının kendisine bağlanan 254 ) bağlantısı üzerinden erişemiyorum /dev/pts/14. Bash nasıl fooyazıyor?
cprn

1
garip, sadece bazı durumlarda çalışıyor gibi görünüyor. sorudaki komut dosyasını kullanarak işe yaramaz. ama bir kabukta "echo $$" yapar ve sonra başka bir kabukta bu pid üzerinde kedi FD 1 yaparsanız, ilk kabukta yazdığım her şey ikincisinde yankılanır.
kelnos

4

İçindeki /dev/ptsdosyalar normal dosyalar değil, sanal terminaller için tutamaçlardır. Bir ptsbazı yaygın olanları şunlardır: okuma ve yazma için davranış (olduğunu, orada daha sonra normal bir dosya veya bir fifo / boru gibi, ondan okunabilir içinde ne yazdığını), ancak sanal terminali oluşturulan süreç aracılık simetrik değildir xterm veya ssh veya agetty veya ekran. Kontrol işlemi genellikle ptsdosyayı okuyan işlemlere tuş basışı gönderir ve üzerine yazdıklarını ekranda görüntüler pts.

Böylece, tail -f /dev/pts/14size komut başladı hangi terminalde dokunun tuşları yazdırır ve bunu yaparsanız mesaj terminalinde görünecektir.echo meh > /dev/pts/14meh


Pts cihazına yazabileceğimi söylemeye haklısın ama ondan okuyamıyorum. İçinde olduğu gibi: tail -f /dev/pts/14o terminale dokunduğum tuşları yazdırmıyor. Yine de ilginç bir cevap. Teşekkürler.
cprn

0

Ben buldum süre önce tür olduğunu geçici çözüm bazen varsayarak STDOUT outputted seyi kontrol etmek gerekliliğini cevaplar Eğer bir var pidsürecinin ve gözleri düşmanca sonuçlara çıplak edebilirsiniz:

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

-2

Sanırım, bunun için kuyruklamak yerine, yapmanız gereken şey çıkışı izlemek olacaktır.

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

Umarım ihtiyacınız olan şey budur.


3
Bu komut, stdout'taki içerik çıktısını değil, her 2 saniyede bir açık fds listesini gösterir .
Ángel

Ángel, doğru. Hangi tanımlayıcıyı izlemek istediğini görmek için saati bir kedi ile birlikte kullanabilir. Sanırım @ peter-horvath, soru için mükemmel bir açıklama yaptı.
Jayesh

Biliyorum watch. Yapmaya çalıştığım zaten çalışan işlemin çıktısını bakmak, bu yüzden watchyardımcı olmuyor.
cprn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.