Mengapa saya tidak bisa `tail -f / proc / $ pid / fd / 1`?

10

Saya menulis sebuah skrip sederhana yang echomerupakan PID-nya:

#/bin/bash

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

Saya menjalankan skrip tersebut (dikatakan 3844berulang kali) di satu terminal dan mencoba ke taildeskriptor file di terminal lain:

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

Itu tidak mencetak apa pun ke layar dan hang sampai ^c. Mengapa?

Juga, semua deskriptor file STD (IN / OUT / ERR) tautan ke Poin yang sama:

$ 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

Apakah ini normal?

Menjalankan Ubuntu GNOME 14.04.

Jika menurut Anda pertanyaan ini milik SO atau SU dan bukan UL, katakan.

cprn
sumber

Jawaban:

13

Make a straceof tail -f, itu menjelaskan semuanya. Bagian yang menarik:

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)

Apa itu? Ini mengatur inotifypenangan ke file, dan kemudian menunggu sampai terjadi sesuatu dengan file ini. Jika kernel mengatakan tailmelalui penangan inotify ini, bahwa file berubah (biasanya ditambahkan), maka tail1) mencari 2) membaca perubahan 3) menuliskannya ke layar.

/proc/3844/fd/1pada sistem Anda adalah tautan simbolis ke /dev/pts/14, yang merupakan perangkat karakter. Tidak ada yang namanya "peta memori", yang bisa diakses dengan itu. Dengan demikian, tidak ada perubahan yang dapat ditandatangani ke inotify, karena tidak ada area disk atau memori yang dapat diakses oleh itu.

Perangkat karakter ini adalah terminal virtual, yang secara praktis berfungsi seolah-olah itu adalah soket jaringan. Program yang berjalan di terminal virtual ini terhubung ke perangkat ini (seperti jika Anda telnet-ted ke port tcp), dan menulis apa yang ingin mereka tulis. Ada hal-hal yang lebih kompleks juga, misalnya mengunci layar, urutan kontrol terminal dan semacamnya, ini biasanya ditangani oleh ioctl()panggilan.

Saya pikir, Anda ingin entah bagaimana menonton terminal virtual. Ini dapat dilakukan di linux, tetapi tidak begitu sederhana, perlu beberapa fungsionalitas seperti proxy jaringan, dan sedikit penggunaan ioctl()panggilan ini yang rumit . Tetapi ada alat yang bisa melakukan itu.

Saat ini saya tidak ingat, paket debian mana yang memiliki alat untuk tujuan ini, tetapi dengan sedikit googling Anda dapat menemukannya dengan mudah.

Ekstensi: seperti yang disebutkan @Jajesh di sini (beri dia +1 jika Anda memberi saya), alat ini dinamai watch.

Extension # 2: @kelnos menyebutkan, simpel cat /dev/pts/14juga cukup. Saya mencobanya, dan ya, itu berhasil, tetapi tidak dengan benar. Aku tidak bereksperimen banyak dengan itu, tetapi tampaknya seolah output akan menjadi yang terminal virtual pergi baik dengan catperintah, atau ke lokasi semula, dan tidak pernah keduanya. Tapi itu tidak pasti.

peterh - Pasang kembali Monica
sumber
jawaban peterh tentang tailitu benar (arloji yang tidak berlaku), tetapi dia salah karena sebenarnya sangat sederhana untuk melakukan apa yang Anda inginkan: cukup gunakan catsaja tail.
kelnos
@ Selnos Terima kasih, saya akan mencoba dan memperluas jawaban saya dengan hasilnya.
peterh
@ Selnos cattidak bekerja untuk saya juga, itu menggantung dengan cara yang sama tidak dan yang bisa saya lakukan adalah melakukannya ctrl+c.
cprn
1
Saya masih belum mengerti. Aku berubah echo $$untuk echo $$ >> foojadi sekarang ada file dan proses membukanya dan menambahkan untuk itu setiap 0,5 detik. Saya masih tidak dapat mengaksesnya melalui deskriptor file dan semua deskriptor file di /proc/$pid/fd/(tetapi 254 yang terhubung ke test.shskrip itu sendiri) /dev/pts/14. Bagaimana cara bash mengaksesnya foo?
cprn
1
anehnya, tampaknya hanya berfungsi dalam beberapa situasi. menggunakan skrip dalam pertanyaan, itu tidak berfungsi. tetapi jika saya melakukan "echo $$" di shell, dan kemudian cat FD 1 pada pid itu di shell lain, semua yang saya ketik di shell pertama di echo di yang kedua.
kelnos
4

File dalam /dev/ptsbukan file biasa, mereka menangani untuk terminal virtual. Sebuah ptsperilaku untuk membaca dan menulis tidak simetris (yaitu, apa yang tertulis di sana nantinya dapat membaca dari itu, seperti file biasa atau FIFO / pipa), tetapi dimediasi oleh proses yang menciptakan terminal virtual: beberapa yang umum adalah xterm atau ssh atau agetty atau layar. Proses pengendalian biasanya akan mengirimkan penekanan tombol ke proses yang membaca ptsfile, dan menampilkan apa yang mereka tulis di layar pts.

Dengan demikian, tail -f /dev/pts/14akan mencetak kunci Anda tekan pada terminal dari mana Anda mulai naskah Anda, dan jika Anda melakukannya echo meh > /dev/pts/14dengan mehpesan akan muncul di terminal.

pqnet
sumber
Anda benar mengatakan saya bisa menulis ke perangkat pts tetapi sepertinya saya tidak bisa membacanya. Seperti pada: tail -f /dev/pts/14tidak mencetak tombol yang saya ketuk pada terminal itu. Itu jawaban yang menarik. Terima kasih.
cprn
0

Beberapa waktu yang lalu saya menemukan agak atasi bahwa kadang-kadang menjawab kebutuhan untuk memeriksa apa yang sedang dikeluarkan ke STDOUT, dengan asumsi Anda memiliki pidproses dan Anda dapat telanjang mata hasil tidak ramah:

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

Saya kira, untuk ini daripada membuntuti, apa yang perlu Anda lakukan adalah menonton hasilnya.

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

Semoga ini yang Anda butuhkan.

Jayesh
sumber
3
Perintah ini akan menampilkan daftar open fds setiap 2 detik, bukan output konten pada stdout.
Ángel
Ángel, benar. Dia bisa menggunakan arloji dengan kucing untuk melihat hasil deskriptor mana yang ingin dia pantau. Saya kira @ peter-horvath, memberikan penjelasan yang sempurna untuk pertanyaan itu.
Jayesh
Aku tahu watch. Apa yang saya coba lakukan adalah mengintip output dari proses yang sudah berjalan, jadi watchtidak membantu.
cprn