ทำไมฉันถึงไม่สามารถ 'tail -f / proc / $ pid / fd / 1` ได้?


10

ฉันเขียนสคริปต์ง่ายๆซึ่งechoเป็น PID:

#/bin/bash

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

ฉันกำลังเรียกใช้สคริปต์ดังกล่าว (มันบอก3844ซ้ำแล้วซ้ำอีก) ใน terminal หนึ่งและพยายามที่จะtailอธิบายไฟล์ในอีกหนึ่ง:

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

^cมันไม่ได้พิมพ์อะไรไปที่หน้าจอและแฮงค์จน ทำไม?

นอกจากนี้ลิงก์ตัวอธิบายไฟล์ STD ทั้งหมด (IN / OUT / ERR) ไปยัง pts เดียวกัน:

$ 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

เป็นเรื่องปกติหรือไม่

ใช้ Ubuntu GNOME 14.04

หากคุณคิดว่าคำถามนี้เป็นของ SO หรือ SU แทนที่จะเป็น UL ให้บอก


คำตอบ:


13

ทำstraceจากtail -fมันอธิบายทุกอย่าง ส่วนที่น่าสนใจ:

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)

มันทำอะไร มันตั้งค่าinotifyตัวจัดการไฟล์และรอจนกว่าจะมีบางอย่างเกิดขึ้นกับไฟล์นี้ หากเคอร์เนลแจ้งtailผ่านตัวจัดการ inotify นี้ว่าไฟล์มีการเปลี่ยนแปลง (ปกติถูกผนวกเข้า) แล้วtail1) ค้นหา 2) อ่านการเปลี่ยนแปลง 3) เขียนพวกเขาออกไปที่หน้าจอ

/proc/3844/fd/1ในระบบของคุณเป็นลิงก์สัญลักษณ์/dev/pts/14ซึ่งเป็นอุปกรณ์ตัวอักษร ไม่มีสิ่งเช่นเดียวกับบางอย่างเช่น "แผนที่หน่วยความจำ" ซึ่งสามารถเข้าถึงได้โดยที่ ดังนั้นจึงไม่มีสิ่งใดที่การเปลี่ยนแปลงอาจถูกลงชื่อเข้าใช้ inotify เนื่องจากไม่มีพื้นที่ดิสก์หรือหน่วยความจำที่สามารถเข้าถึงได้โดยที่

อุปกรณ์ตัวละครนี้เป็นเทอร์มินัลเสมือนซึ่งใช้งานได้จริงราวกับว่ามันเป็นซ็อกเก็ตเครือข่าย โปรแกรมที่รันบนเทอร์มินัลเสมือนนี้กำลังเชื่อมต่อกับอุปกรณ์นี้ (เช่นเดียวกับที่คุณเทลเน็ตลงในพอร์ต tcp) และเขียนสิ่งที่พวกเขาต้องการเขียนลงไป มีสิ่งที่ซับซ้อนเช่นกันเช่นการล็อกหน้าจอลำดับการควบคุมเทอร์มินัลและสิ่งเหล่านี้มักจัดการโดยการioctl()โทร

ฉันคิดว่าคุณต้องการดูเทอร์มินัลเสมือนจริง มันสามารถทำได้บน linux แต่มันไม่ง่ายมันต้องการฟังก์ชั่นที่คล้ายกับเครือข่ายพร็อกซี่และการใช้งานioctl()สายที่ยุ่งยากเล็กน้อย แต่มีเครื่องมือที่สามารถทำได้

ขณะนี้ฉันจำไม่ได้ว่าแพ็คเกจเดเบียนชนิดใดมีเครื่องมือสำหรับเป้าหมายนี้ แต่ด้วย googling เล็กน้อยคุณสามารถค้นหาได้อย่างง่ายดาย

ส่วนขยาย:เป็น @Jajesh กล่าวถึงที่นี่ (ให้เขา +1 ถ้าคุณให้ฉัน) watchเครื่องมือที่มีชื่อว่า

ส่วนขยาย # 2: @kelnos พูดถึงเรื่องง่ายcat /dev/pts/14ก็เพียงพอแล้ว ฉันลองมันและใช่มันใช้งานได้ แต่ไม่ถูกต้อง ผมไม่ได้ทดลองมากกับที่ แต่มันดูเหมือนว่าฉันราวกับว่าการส่งออกจะเข้าสู่สถานีเสมือนที่หายไปอย่างใดอย่างหนึ่งกับcatคำสั่งหรือไปยังตำแหน่งเดิมและไม่เคยไปทั้งสอง แต่ก็ไม่แน่ใจ


คำตอบ peterh เกี่ยวกับtailความถูกต้อง (บิตนาฬิกา inotify) แต่เขาไม่ถูกต้องในการที่จะเป็นจริงมากง่ายที่จะทำสิ่งที่คุณต้องการ: เพียงแค่ใช้แทนcat tail
kelnos

@kelnos ขอบคุณฉันจะลองและขยายคำตอบของฉันกับผลลัพธ์
peterh - Reinstate Monica

@kelnos ไม่ทำงานสำหรับฉันอย่างใดอย่างหนึ่งมันแฮงค์แบบเดียวกับที่หางไม่และทั้งหมดที่ผมสามารถทำได้คือการcat ctrl+c
cprn

1
ฉันยังไม่เข้าใจ ฉันเปลี่ยนecho $$เป็นecho $$ >> fooตอนนี้มีไฟล์และกระบวนการเปิดและต่อท้ายทุกๆ 0.5 วินาที ฉันยังคงไม่สามารถเข้าถึงได้ผ่านทางอธิบายไฟล์และทุกอธิบายไฟล์ใน/proc/$pid/fd/( แต่ 254 ซึ่งเชื่อมโยงไปยังtest.shสคริปต์เอง) /dev/pts/14เชื่อมโยงไปยัง การเข้าถึง bash fooนั้นเขียนถึงได้อย่างไร?
cprn

1
มันดูเหมือนว่าจะทำงานในบางสถานการณ์เท่านั้น ใช้สคริปต์ในคำถามมันไม่ทำงาน แต่ถ้าฉันทำ "echo $$" ในเชลล์แล้ว cat FD 1 บน pid นั้นในเชลล์อื่นทุกอย่างที่ฉันพิมพ์ในเชลล์แรกนั้นถูก echoed ในวินาที
kelnos

4

ไฟล์ใน/dev/ptsไม่ใช่ไฟล์ปกติ แต่เป็นไฟล์ที่จัดการกับเทอร์มินัลเสมือน ptsพฤติกรรมสำหรับการอ่านและการเขียนที่ไม่สมมาตร (นั่นคือสิ่งที่เขียนในนั้นสามารถอ่านจากมันเช่นแฟ้มปกติหรือ FIFO / ท่อ) แต่ผู้ไกล่เกลี่ยโดยกระบวนการที่สร้าง terminal เสมือน: บางคนที่ร่วมกันคือ xterm หรือ ssh หรือ agetty หรือหน้าจอ กระบวนการควบคุมโดยปกติแล้วจะจัดส่งกดปุ่มกระบวนการที่อ่านไฟล์และการแสดงผลบนหน้าจอสิ่งที่พวกเขาเขียนในptspts

ดังนั้นtail -f /dev/pts/14จะพิมพ์คีย์คุณแตะที่ขั้วจากที่คุณเริ่มต้นสคริปต์ของคุณและถ้าหากคุณทำข้อความจะปรากฏในสถานีecho meh > /dev/pts/14meh


คุณพูดถูกฉันสามารถเขียนลงในอุปกรณ์ pts ได้ แต่ฉันไม่สามารถอ่านได้ ใน: tail -f /dev/pts/14ไม่พิมพ์คีย์ที่ฉันแตะบนเทอร์มินัลนั้น มันเป็นคำตอบที่น่าสนใจ ขอบคุณ
cprn

0

เวลาที่ผ่านมาผมพบว่าครับแก้ปัญหาที่บางครั้งคำตอบที่จำเป็นที่จะต้องตรวจสอบสิ่งที่ถูกออกมาเพื่อ STDOUT สมมติว่าคุณมีpidของกระบวนการและคุณสามารถเปลือยสายตาไม่เป็นมิตรผล:

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

-2

ฉันเดาว่าสำหรับเรื่องนี้แทนที่จะทำท้ายสิ่งที่คุณต้องทำคือดูผลลัพธ์

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

หวังว่านี่คือสิ่งที่คุณต้องการ


3
คำสั่งนี้จะแสดงรายการของ fds ที่เปิดอยู่ทุก 2 วินาทีไม่ใช่เอาต์พุตเนื้อหาใน stdout
Ángel

Ángelจริง เขาสามารถใช้นาฬิกากับแมวเพื่อดูผลลัพธ์ที่ตัวบ่งบอกที่เขาต้องการตรวจสอบ ฉันเดา @ peter-horvath ให้คำอธิบายที่สมบูรณ์แบบสำหรับคำถาม
Jayesh

watchฉันรู้ว่า สิ่งที่ฉันพยายามทำคือการมองเอาท์พุทของกระบวนการที่ทำงานอยู่แล้วดังนั้นจึงwatchไม่ช่วย
cprn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.