動作中のプロセスのptyをつなぎかえられる、reptyrを使ってみる

Pocket

UNIX板のGNU screenスレッドで紹介されていたreptyrを使ってみました。

screen外のプロセスにattachさせる

既にscreenを実行している状況で、screenのセッション外のプロセスを起動してみます。適当なterminalを起動するなり、外からsshでつなげるなりしてみます。あとでプロセスを探しやすいようにttyコマンドで現在使っているptyデバイスが何かを確認しておきます。

$ tty
/dev/pts/7

次にscreen内の任意のウインドウのshellから、当該プロセスにつなげてみます。

$ reptyr -s `pgrep -t pts/7 bash`
[-] Timed out waiting for child stop.
[+] Allocated scratch page: 7faebd18b000
[+] Opened the new tty in the child: 3
[+] Set the controlling tty
$

この時点で、元のターミナルは無反応になり、bashの制御がscreen下に移りました。shellを終了すればreptyrに制御が戻ります。

$ exit
ログアウト
$

gdbと組み合わせる

reptyrのもう一つの機能、ptyを外部から使わせるために確保する-lオプションを使ってみます。

$ reptyr -l
Opened a new pty: /dev/pts/7

別のshellからgdbでこのptyを使ってみます。set inferior-ttyで/dev/pts/7を指定することで、gdbが動かすプロセスの出力をreptyr側の端末に変更できます。

$ gdb ls
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /bin/ls...(no debugging symbols found)...done.
(gdb) set inferior-tty /dev/pts/7
(gdb) run
Starting program: /bin/ls
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Inferior 1 (process 15662) exited normally]
(gdb)

reptyrを実行していたshell上に、lsの出力が表示されます。標準入出力をデバッガの画面と切り離すことができて便利です。

実装方法

以前「起動済みプロセスのリダイレクト先を設定したい」という記事を見かけた記憶があったので、基本的には同じようなやりかただろうと思いつつソースを見てみたら、その通りでした。

起動しているプロセスに対してptrace(2)でattachし、ptyをdup2でfile descripter 0, 1, 2に複製しています。ただし、単なるリダイレクトと違い仮想端末が相手なのでresize等に対応するためのコードも含まれているようです。

前述の記事や本プログラムのドキュメントにもありますが、Ubuntuのカーネルはデフォルトで一般ユーザーのptraceを禁止しています。procfsを見てそのあたりをチェックするコードも入っています。Ubuntuユーザーが利用する場合、rootで実行するか、sysctlの設定を変更する必要があります。