왜 `tail -f /proc/$pid/fd/1`을 할 수 없나요?

왜 `tail -f /proc/$pid/fd/1`을 할 수 없나요?

나는 PID를 포함하는 간단한 스크립트를 작성했습니다 echo.

#/bin/bash

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

나는 3844한 터미널에서 해당 스크립트를 실행하고 (반복적으로 말함) tail다른 터미널에서 파일 설명자를 실행하려고합니다.

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

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

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

$ 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에 속한다고 생각되면 알려주시기 바랍니다.

답변1

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(). 하지만 이를 가능하게 해주는 도구가 있습니다.

지금은 어떤 데비안 패키지에 이 작업을 수행할 수 있는 도구가 있는지 기억나지 않지만, 조금만 인터넷 검색을 하면 쉽게 찾을 수 있을 것입니다.

확장하다:@Jajesh가 여기에서 언급했듯이(나에게 제공한 경우 +1) 도구 이름은 입니다 watch.

확장 #2:@kelnos는 간단한 것만으로도 cat /dev/pts/14충분하다고 언급했습니다. 나는 그것을 시도했고 네, 작동하지만 올바르지 않습니다. 이것저것 많이 실험해보진 않았지만 저 가상터미널로 들어가는 출력이 사라지는 것 같아요누구나명령 또는 원래 위치 로 이동 cat하되 동시에 둘 다로 이동하지 마십시오. 그러나 이것은 확실하지 않습니다.

답변2

의 파일은 /dev/pts일반 파일이 아니며 가상 터미널에 대한 핸들입니다. 읽기 및 쓰기 동작은 pts대칭이 아니지만(즉, 작성된 내용은 일반 파일이나 fifo/파이프처럼 나중에 읽을 수 있음) 가상 터미널을 생성하는 프로세스에 의해 규제됩니다. 몇 가지 일반적인 동작은 xterm 또는 SSH 또는 agetty 또는 화면. 제어 프로세스는 일반적으로 pts파일을 읽고 이를 화면에 렌더링하는 프로세스 에 키 입력을 전달합니다 pts.

따라서 tail -f /dev/pts/14스크립트를 시작한 터미널에서 누른 키가 출력되며, 이렇게 하면 터미널에 echo meh > /dev/pts/14메시지가 나타납니다.meh

답변3

얼마 전에 나는 하나를 발견했다.약간해결책때때로pid프로세스가 있고 친숙하지 않은 결과를 볼 수 있다고 가정하고 STDOUT에 출력되는 내용을 확인해야 할 필요성에 응답합니다 .

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

답변4

이를 위해 해야 할 일은 tail이 아니라 출력을 지켜보는 것입니다.

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

이것이 당신에게 필요한 것이기를 바랍니다.

관련 정보