私が行う場合:
_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)"
_
lsof
によって返されたpid/fdのそれぞれについて、そのマッピングを構築しますが、その情報を取得するためのより直接的で信頼性が高く、邪魔にならない方法はありますか?
最初に、/proc/locks
で見つけた情報に基づいて、いくつかのxterm
sをxterm
pidにトレースしてみましたが、緩いものでした。つまり、うまくいったとは思いますが、せいぜい状況依存でした。ファイルが提供するすべての情報を完全に理解しているわけではなく、ファイルの内容と既知の端末プロセスの間で対応しているように見えるものにのみ一致していました。
次に、pty間のアクティブなlsof/strace
プロセスでwrite/talk
を見てみました。私は実際にはどちらのプログラムも使用したことがありませんが、utmp
に依存しているようです。対象のptyにutmp
エントリがなかった場合、なんらかの理由で、その存在を認めることを拒否しました。多分それを回避する方法がありますが、私はそれを放棄するのに十分混乱していました。
/proc/tty/drivers
でudevadm
とpts
にそれぞれアドバタイズされるように、136と128のメジャー番号のデバイスノードでptm
の検出を試みましたが、非常に便利な経験もありませんそのツールを使用して、再び実質的なものは何も見つかりませんでした。興味深いことに、私は両方のデバイスタイプの:min
範囲が驚異的な0-1048575
でリストされていることに気付きました。
しかし、これを再訪するまでは このカーネルドキュメント でしたが、mount
sの観点から問題について考え始めました。以前に何度か読んだことがありましたが、その行での継続的な調査が私にこれを導いたとき this 2012 /dev/pts
patchset アイデアがありました:
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
$$
num \0
nullバイトを各ptyに出力し、以前のチェックに対して各マスタープロセスのioをチェックします。違いが$$
の場合、pidをptyに関連付けます。これはほとんど機能します。つまり、私にとっては、次を返します:
410 owns /dev/pts/0
410 owns /dev/pts/1
710 owns /dev/pts/2
これは正しいですが、明らかに、少々際どいです。つまり、それらの1つがその時点で大量のデータを読み取っていた場合、おそらく見落とすことになります。最初にストップビットを送信するために別のptyのstty
モードを変更する方法を理解しようとしています。
Qemuでも同じ問題が発生し、最終的に非常に悪い解決策が見つかりました(ただし、解決策はまだあります)。プロセスメモリの解析です。
これは、qemuがリモートのPTSを特定の形式の文字列に格納し、ヒープに割り当てていることを知っているため、ここで機能しています。いくつかの変更を加え、フューザー出力からpidを再利用することで、他の状況でも機能する可能性があります(他の回答を確認してください)。
コードは here から変更されています。
#! /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()
接続の所有者と接続元を探しているだけの場合は、 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 で最後に表示されます。
$ 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を取得するには、psを、表示しているttyセッションに制限します。起動するのにまったく邪魔にならない。
$ 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