私が次のことをしたら:
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
私は以前に2つのプログラムを実際に使用したことがありませんが、それに依存しているようです。何らかの理由で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
正しい言葉ですが、明らかに少し不自然です。私の言うことは、それらの1つがその時点で大量のデータを読んでいる場合、それを見逃す可能性があるということです。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()