Sté*_*las 29 terminal-emulator open-files pty
如果我做:
echo foo > /dev/pts/12
Run Code Online (Sandbox Code Playgroud)
某些进程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)"
Run Code Online (Sandbox Code Playgroud)
对于lsof
构建该映射而返回的每个 pid/fd ,是否有更直接、可靠且侵入性更小的方法来获取该信息?
起初,我尝试根据我找到的信息追踪 pid xterm
,但它是松散的。我的意思是,我认为它有效,但充其量只是环境 - 我不完全理解该文件提供的所有信息,并且仅匹配其内容和已知终端进程之间似乎对应的信息。xterm
/proc/locks
然后我尝试观察pty 之间的lsof/strace
活动write/talk
进程。我以前从未真正使用过这两个程序,但它们似乎依赖于utmp
. 如果我的目标 pty 出于某种原因没有utmp
条目,他们都拒绝承认它的存在。也许有办法解决这个问题,但我很困惑而放弃了它。
我尝试udevadm
使用 136 和 128 个主设备节点进行一些发现,分别在pts
和中进行了广告,但我也缺乏使用该工具的任何非常有用的经验,并且再次没有发现任何实质性内容。但有趣的是,我注意到这两种设备类型的范围都以惊人的价格列出。ptm
/proc/tty/drivers
:min
0-1048575
不过,直到我重新审视这个内核文档,我才开始从mount
s 角度思考这个问题。我之前已经读过好几次了,但是当对该行的持续研究引导我找到这个 2012 年/dev/pts
补丁集时,我有了一个想法:
sudo fuser -v /dev/ptmx
Run Code Online (Sandbox Code Playgroud)
我想我通常用什么来将进程与 关联起来mount
?果然:
USER PID ACCESS COMMAND
/dev/ptmx: root 410 F.... kmscon
mikeserv 710 F.... terminology
Run Code Online (Sandbox Code Playgroud)
因此,有了这些信息,我可以做的事情,例如terminology
:
sudo sh -c '${cmd:=grep rchar /proc/410/io} && printf 1 >/dev/pts/0 && $cmd'
###OUTPUT###
rchar: 667991010
rchar: 667991011
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,通过一些显式测试,可以使这样的过程非常可靠地输出任意 pty 的主进程。关于套接字,我相当确定可以从那个方向接近它,也可以使用socat
而不是调试器,但我还没有弄清楚如何实现。不过,我怀疑ss
如果你比我更熟悉它可能会有所帮助:
sudo sh -c 'ss -oep | grep "$(printf "pid=%s\n" $(fuser /dev/ptmx))"'
Run Code Online (Sandbox Code Playgroud)
因此,我实际上进行了一些更明确的测试来设置它:
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
Run Code Online (Sandbox Code Playgroud)
它向每个 pty 打印$$
num\0
个空字节,并根据之前的检查检查每个主进程的 io。如果不同,$$
则它将 pid 与 pty 相关联。这大多有效。我的意思是,对我来说,它返回:
410 owns /dev/pts/0
410 owns /dev/pts/1
710 owns /dev/pts/2
Run Code Online (Sandbox Code Playgroud)
这是正确的,但是,显然,这有点活泼。我的意思是,如果其中一个当时正在读取一堆数据,它可能会错过。我正在尝试找出如何更改stty
另一个 pty 上的模式,以便首先发送停止位或类似的内容,以便我可以修复该问题。
小智 2
2017 年,Linux 获得了一项新功能,可以稍微简化此过程(提交d01c3289e7d,在 Linux 4.14 及更高版本中可用)
获取打开的进程列表后/dev/ptmx
:
$ fuser dev/ptmx
/dev/ptmx: 1330334 1507443
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
结果是从 a<pid>:<ptmx fd>
到相应的映射/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
Run Code Online (Sandbox Code Playgroud)
$ 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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6391 次 |
最近记录: |