왜`tail -f / proc / $ pid / fd / 1`을 할 수 없습니까?


10

echoPID 를 나타내는 간단한 스크립트를 작성했습니다 .

#/bin/bash

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

3844한 터미널에서 스크립트를 반복 실행 하고 다른 터미널 tail에서 파일 설명자를 시도 하고 있습니다.

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

화면에 아무것도 인쇄하지 않고까지 멈 춥니 다 ^c. 왜?

또한 모든 STD 파일 설명자 (IN / OUT / ERR)는 동일한 pt에 연결됩니다.

$ 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

이것이 정상입니까?

우분투 그놈 14.04 실행.

이 질문이 UL 대신 SO 또는 SU에 속한다고 생각되면 알려주십시오.


답변:


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()통화로 처리됩니다 .

나는 당신이 어떻게 든 가상 단말기를보고 싶다고 생각합니다. 리눅스에서 할 수는 있지만 그렇게 간단하지는 않으며 네트워크 프록시와 같은 기능이 필요하며 이러한 ioctl()호출 의 약간 까다로운 사용법이 필요 합니다. 그러나 그렇게 할 수있는 도구가 있습니다.

현재 어떤 데비안 패키지 가이 목표를위한 도구를 가지고 있는지 기억이 나지 않지만 약간의 인터넷 검색으로 쉽게 찾을 수 있습니다.

확장 : @Jajesh가 여기에서 언급했듯이 (당신이 나에게 준 경우 +1을주십시오), 도구의 이름은 watch입니다.

확장 # 2 : @kelnos가 언급했듯이 단순함 cat /dev/pts/14도 충분했습니다. 나는 그것을 시도했지만 그렇습니다. 그러나 제대로 작동하지 않았습니다. 나는 그와 많은 실험을하지 않았다, 그러나 출력이 사라 가상 터미널로가는 경우 같은 날 것으로 보인다 하거나 받는 cat명령 또는 원래 위치로, 결코 모두. 그러나 확실하지 않습니다.


peterh의 대답 tail은 정확하지만 ( intotify watch bit) 실제로 원하는 것을 수행하는 것이 매우 간단 하다는 점에서 잘못되었습니다 . cat대신 간단히 사용하십시오 tail.
— kelnos

@ kelnos 감사합니다, 나는 그것을 시도하고 결과와 함께 내 대답을 확장합니다.
— peterh-Reinstate Monica

@kelnos cat는 나 에게도 효과 가 없으며 꼬리와 같은 방식으로 매달리고 내가 할 수있는 모든 것은입니다 ctrl+c.
— cprn

1
나는 아직도 그것을 얻지 못한다. 나는 변경 echo $$에 echo $$ >> foo이제이 파일의 공정은 0.5 초마다 그것을 열고 여기에 추가합니다. 나는 여전히 파일 디스크립터와 /proc/$pid/fd/( test.sh스크립트 자체에 링크되는 254 ) 링크의 모든 파일 디스크립터를 통해 액세스 할 수 없습니다 /dev/pts/14. bash foo는 쓰기에 어떻게 액세스 합니까?
— cprn

1
이상하게도 일부 상황에서만 작동하는 것으로 보입니다. 질문에 스크립트를 사용하면 작동하지 않습니다. 그러나 쉘에서 "echo $$"를 수행 한 다음 다른 쉘의 해당 pid에서 cat FD 1을 수행하면 첫 번째 쉘에 입력 한 모든 것이 두 번째에 에코됩니다.
— kelnos

4

파일 /dev/pts은 일반 파일이 아니며 가상 터미널에 대한 핸들입니다. pts몇 가지 일반적인 것들입니다 : 읽기 및 쓰기 동작 (즉,이 나중에 일반 파일 또는 FIFO / 파이프처럼, 그것에서 읽을 수로 작성 무슨)하지만 가상 터미널을 생성하는 과정에 의해 매개 대칭되지 않습니다 xterm 또는 ssh 또는 agetty 또는 화면. 제어 프로세스는 일반적으로 pts파일 을 읽는 프로세스에 키 누름을 전달하고 파일에 작성된 내용을 화면에 렌더링합니다 pts.

따라서, 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
이 명령은 stdout 의 내용 출력이 아니라 2 초마다 열린 fd 목록을 표시합니다 .
— Ángel

앵겔, 맞아 그는 고양이와 함께 시계를 사용하여 모니터링하려는 설명자 결과를 확인할 수 있습니다. @ peter-horvath가 그 질문에 대한 완벽한 설명을했다고 생각합니다.
— Jayesh

알고 watch있습니다. 내가하려고하는 것은 이미 실행중인 프로세스의 출력을 들여다 보는 것이므로 watch도움이되지 않습니다.
— cprn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.