내가 다음을 수행하면:
echo foo > /dev/pts/12
일부 프로세스는 foo\n
파일 설명자에서 마스터로 이를 읽습니다.
해당 프로세스가 무엇인지 알아낼 수 있는 방법이 있나요?
또는 다른 말로 하면, 어느 xterm/sshd/script/screen/tmux/expect/socat...가 반대편에 있는지 어떻게 알 수 있습니까 /dev/pts/12
?
lsof /dev/ptmx
pty의 마스터 측에 파일 설명자가 있는 프로세스를 알려줍니다. 프로세스 자체는 ptsname()
( TIOCGPTN
ioctl )을 사용하여 자체 fd를 기반으로 마스터 장치를 찾을 수 있으므로 다음을 사용할 수 있습니다.
gdb --batch --pid "$the_pid" -ex "print ptsname($the_fd)"
이 맵은 반환된 각 pid/fd에 대해 작성되었지만 lsof
이 정보를 얻는 더 직접적이고 안정적이며 덜 침해적인 방법이 있습니까?
답변1
처음에는 찾은 정보를 바탕으로 pid를 추적해 보았지만 xterm
느슨했습니다. 내 말은, 작동한다고 생각하지만 기껏해야 상황에 따른 것입니다. 해당 파일에서 제공하는 모든 정보를 완전히 이해하지 못하고 해당 내용과 알려진 터미널 프로세스 간에 일치하는 것으로 보이는 것만 일치합니다.xterm
/proc/locks
그런 다음 pty 사이의 lsof/strace
활성 프로세스를 관찰하려고 합니다. write/talk
나는 이전에 두 프로그램을 실제로 사용한 적이 없지만 그것에 의존하는 것 같습니다 . 어떤 이유로 utmp
내 대상 pty에 항목이 없으면 둘 다 그 존재를 인정하지 않습니다. utmp
어쩌면 이 문제를 해결할 수 있는 방법이 있을지도 모르지만, 혼란스러워서 포기했습니다.
나는 udevadm
각각 및 에 광고된 136개 및 128개의 마스터 장치 노드를 사용하여 몇 가지 발견을 pts
시도 ptm
했지만 /proc/tty/drivers
해당 도구에 대한 매우 유용한 경험이 부족했으며 다시 한 번 실질적인 내용을 찾지 못했습니다. 그러나 흥미롭게도 :min
두 가지 장치 유형 모두 놀라운 가격으로 나열되어 있다는 것을 알았습니다 0-1048575
.
이걸 다시 보기 전까지는이 커널 문서그러나 나는 이 문제를 s의 관점에서 생각하기 시작했다 mount
. 나는 이전에 이 내용을 여러 번 읽었지만 해당 분야에 대한 지속적인 연구를 통해 이것을 발견하게 되었습니다.이 2012 /dev/pts
패치 세트나는 아이디어가:
sudo fuser -v /dev/ptmx
제 생각에는프로세스를 와 연결하려면 일반적으로 무엇을 사용합니까 mount
?정말:
USER PID ACCESS COMMAND
/dev/ptmx: root 410 F.... kmscon
mikeserv 710 F.... terminology
따라서 이 정보를 사용하여 다음과 같은 작업을 수행할 수 있습니다 terminology
.
sudo sh -c '${cmd:=grep rchar /proc/410/io} && printf 1 >/dev/pts/0 && $cmd'
###OUTPUT###
rchar: 667991010
rchar: 667991011
보시다시피, 몇 가지 명시적인 테스트를 통해 이러한 프로세스를 만들어 임의의 pty의 기본 프로세스를 매우 안정적으로 출력할 수 있습니다. 소켓에 관해서는 디버거를 사용하는 것보다 그 방향에서 접근하는 것이 가능하다고 확신 socat
하지만 아직 방법을 찾지 못했습니다. 그러나 ss
당신이 나보다 더 잘 알고 있다면 도움이 될 것이라고 생각합니다.
sudo sh -c 'ss -oep | grep "$(printf "pid=%s\n" $(fuser /dev/ptmx))"'
그래서 실제로 설정을 위해 좀 더 명시적인 테스트를 수행했습니다.
sudo sh <<\CMD
chkio() {
read io io <$1
dd bs=1 count=$$ </dev/zero >$2 2>/dev/null
return $((($(read io io <$1; echo $io)-io)!=$$))
}
for pts in /dev/pts/[0-9]* ; do
for ptm in $(fuser /dev/ptmx 2>/dev/null)
do chkio /proc/$ptm/io $pts && break
done && set -- "$@" "$ptm owns $pts"
done
printf %s\\n "$@"
CMD
각 pty에 $$
num null 바이트를 인쇄 \0
하고 이전 확인과 비교하여 각 기본 프로세스의 io를 확인합니다. 다른 경우 $$
pid를 pty와 연결합니다. 이것최대일하다. 내 말은, 나에게는 다음과 같이 반환됩니다.
410 owns /dev/pts/0
410 owns /dev/pts/1
710 owns /dev/pts/2
맞는 말이긴 한데, 분명히 조금은 부자연스럽습니다. 내 말은, 그들 중 하나가 그 당시에 많은 양의 데이터를 읽고 있다면 그것을 놓칠 수도 있다는 것입니다. stty
문제를 해결할 수 있도록 정지 비트가 먼저 전송되도록 다른 pty에서 모드를 변경하는 방법을 알아내려고 노력 중입니다 .
답변2
2017년에 Linux에는 이 프로세스를 약간 더 쉽게 만드는 새로운 기능이 추가되었습니다(커밋d01c3289e7d, Linux 4.14 이상의 경우)
열린 프로세스 목록을 얻은 후 /dev/ptmx
:
$ fuser dev/ptmx
/dev/ptmx: 1330334 1507443
pts
다음과 같은 번호를 받을 수 있습니다.
for pid in $(fuser /dev/ptmx 2>/dev/null); do grep -r tty-index /proc/$pid/fdinfo; done
/proc/1330334/fdinfo/13:tty-index: 0
/proc/1330334/fdinfo/14:tty-index: 1
/proc/1330334/fdinfo/27:tty-index: 2
/proc/1330334/fdinfo/28:tty-index: 4
/proc/1507443/fdinfo/3:tty-index: 3
결과는 <pid>:<ptmx fd>
a에서 해당 항목으로의 매핑 입니다./dev/pts/<index>
버전 4.90부터, lsof
이 API를 사용하여 상대방에게 보고 /dev/ptmx
하고 파일을 사용/ /dev/pts/x
열 수 있습니다.-E
+E
$ lsof -E -ad 0 -p $$
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
zsh 14335 user 0u CHR 136,8 0t0 11 /dev/pts/8 14333,xterm,5u
$ lsof +E -ad 0 -p $$
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
xterm 14333 user 5u CHR 5,2 0t0 87 /dev/ptmx ->/dev/pts/8 14335,zsh,0u 14335,zsh,1u 14335,zsh,2u 14335,zsh,10u 14391,lsof,0u 14391,lsof,1u 14391,lsof,2u
zsh 14335 user 0u CHR 136,8 0t0 11 /dev/pts/8 14333,xterm,5u
답변3
누가 연결했는지, 어디서 연결했는지 알아낸다면,WHO명령은 잘 작동할 것입니다.
$ who
falsenames tty8 Jun 13 16:54 (:0)
falsenames pts/0 Jun 16 11:18 (:0)
falsenames pts/1 Jun 16 12:59 (:0)
falsenames pts/2 Jun 16 13:46 (:0)
falsenames pts/3 Jun 16 14:10 (:0)
falsenames pts/4 Jun 16 16:41 (:0)
해당 연결에서 무엇이 듣고 있는지 알고 싶다면,승이는 마지막에 표시됩니다.
$ w
16:44:09 up 2 days, 23:51, 6 users, load average: 0.26, 0.98, 1.25
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
falsenames tty8 :0 Fri16 2days 53:36 0.59s x-session-manager
falsenames pts/0 :0 11:18 5:25m 1:10 1:10 synergys -a 10.23.8.245 -c .synergy.conf -f -d DEBUG
falsenames pts/1 :0 12:59 3:44m 0.05s 0.05s bash
falsenames pts/2 :0 13:46 2:52m 0.11s 0.11s bash
falsenames pts/3 :0 14:10 2:17 0.07s 0.07s bash
falsenames pts/4 :0 16:41 1.00s 0.04s 0.00s w
PID를 얻으려면 현재 보고 있는 tty 세션으로 ps를 제한하십시오. 부팅이 전혀 눈에 띄지 않습니다.
$ ps -t pts/0 --forest
PID TTY TIME CMD
23808 pts/0 00:00:00 bash
23902 pts/0 00:03:27 \_ synergys
시기에 따라 붉은 청어가 생길 수도 있습니다. 그러나 그것은 좋은 출발점입니다.
$ tty
/dev/pts/4
$ ps -t pts/4 --forest
PID TTY TIME CMD
27479 pts/4 00:00:00 bash
3232 pts/4 00:00:00 \_ ps
27634 pts/4 00:00:00 dbus-launch
답변4
나는 qemu와 동일한 문제를 겪었고 마침내 매우 나쁜 해결책(그러나 여전히 해결책)을 찾았습니다: 프로세스 메모리를 구문 분석합니다.
이것은 qemu가 원격 pt를 특정 형식의 문자열로 저장하고 힙에 할당한다는 것을 알고 있기 때문에 여기서 작동합니다. 아마도 다른 경우에도 작동할 것입니다. 몇 가지 사항을 변경하고 퓨전 출력의 pid를 재사용하십시오(다른 답변 확인).
다음에서 수정된 코드여기.
#! /usr/bin/env python
import sys
pid = sys.argv[1]
import re
maps_file = open("/proc/" + pid + "/maps", 'r')
mem_file = open("/proc/" + pid + "/mem", 'r', 0)
for line in maps_file.readlines():
# You may want to remove the 'heap' part to search all RAM
m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r]).*\[heap\]', line)
if m and m.group(3) == 'r':
start = int(m.group(1), 16)
end = int(m.group(2), 16)
mem_file.seek(start)
chunk = mem_file.read(end - start)
# You may want to adapt this one to reduce false matches
idx = chunk.find("/dev/pts/")
if idx != -1:
end = chunk.find("\0", idx)
print chunk[idx:end]
maps_file.close()
mem_file.close()