왜`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.