tmux

Table of Contents

termcap and terminfo

termcap(5) terminfo(5) term(5) あたりに詳しい説明が有る。初代はtermcapな文字列で 端末の挙動を記述したもの。それが巨大になってきたのでtic(1)と言うコンパイラーを 使ってバイナリーにした。それがterminfo。アプリから手軽に利用可能としたのが (n)cursesになる。

初代の文字列ベースが、/usr/src/share/termtypes/termtypes.masterとしてOpenBSDに 収録されてる。

ob$ egrep '^[a-z]' termtypes.master | wc
    1813    9207   89204

雑に調べただけで、1800種類の端末が登録されてる。

ob$ egrep '^[a-z]' termtypes.master | sort | grep kterm
kterm-color|kterm-co|kterm with ANSI colors,
kterm|kterm kanji terminal emulator (X window system),
tt|tkterm|Don Libes' tk text widget terminal emulator,

超昔に世話になった、漢字ターミナルなんてのも残っている。歴史博物館だな。

#### KTERM
# (kterm: this had extension capabilities ":KJ:TY=ascii:" -- esr)
# (kterm should not invoke DEC Graphics as the alternate character set
#  -- Kenji Rikitake)
# (proper setting of enacs, smacs, rmacs makes kterm to use DEC Graphics
#  -- MATSUMOTO Shoji)
# kterm implements acsc via built-in table of X Drawable's
kterm|kterm kanji terminal emulator (X window system),
        XT,
        ncv@,
        acsc=``aajjkkllmmnnooppqqrrssttuuvvwwxx~~,
        csr=\E[%i%p1%d;%p2%dr, enacs=, kmous=\E[M, rc=\E8,
        rmacs=\E(B, rmam=\E[?7l, sc=\E7,
        sgr=\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;m%?%p9%t\E(0%e
            \E(B%;,
        sgr0=\E[m\E(B, smacs=\E(0, smam=\E[?7h, use=x10term+sl,
        use=xterm-r6, use=ecma+color,
kterm-color|kterm-co|kterm with ANSI colors,
        ncv@, use=kterm, use=ecma+color,

中身はこんな暗号に近い記述になってる。termcap(5)が解読用の説明書なんで、読ん でくれたまえ(あなたが古文書学者なら。そう言えば武士の家計簿を解析して大出世 された先生がおおられるな)

infocmp

暗号解読の一助になるユーティリティーが昔から提供されている。本来は各種の terminfoを比較するもの。なんだけど、単独のterminfoでも大丈夫。例として 馬鹿端末(通常の端末はインテリ端末 - これじゃどこかの大学出みたいなんで、 インテリジェント端末と言う)である、dumbを例にしてみる。

ob$ infocmp -l dumb
#       Reconstructed via infocmp from file: /usr/share/terminfo/d/dumb
dumb|80-column dumb tty,
        am,
        cols#80,
        bel=^G, cr=\r, cud1=\n, ind=\n,

逆アセしてくれるんだけど、短縮系でピンとこない。

ob$ infocmp -L dumb
#       Reconstructed via infocmp from file: /usr/share/terminfo/d/dumb
dumb|80-column dumb tty,
        auto_right_margin,
        columns#80,
        bell=^G, carriage_return=\r, cursor_down=\n,
        scroll_forward=\n,

これなら多分大丈夫(GUIユーザー意外の人ね)。

ob$ infocmp -c dumb
comparing dumb to tmux.
    comparing booleans.
        am= T.
        bce= F.
        bw= F.
        :
    comparing numbers.
        cols= 80.
    comparing strings.
        bel= '^G'.
        cr= '\r'.
        cud1= '\n'.
        ind= '\n'.

そしてこちらは、そこはかとなくC言語風。infocmpの本性が表われて、今設定してる 端末(この場合はtmux)との比較結果が表示される。論理値の場合でdumbに存在 しない定義は、Fと表示される。こういったユーティリティもC言語対応になってる。 ubuntuの次期バージョンは、コア・コマンドがrust製になると言われているけど、 そうなると、こう言った資産はどうなるの? そこはかとなく心配。

だったら、そういうのは頑無視して、OpenBSDを母港にすれば宜しい。7.7も順調に リリースされた事だしね。

tty/pty

TTY/PTYに関するクイズ

擬似端末

プロセスのツリーを表示してみる。

sakae@lu:~$ pstree | lv
   :
        |-sddm-+-Xorg---5*[{Xorg}]
        |      |-sddm-helper---lxqt-session-+-agent---3*[{agent}]
        |      |                            |-mlterm---bash---TOGO---tmux: client
        |      |                            |-tmux: server-+-bash-+-less
        |      |                            |              |      `-pstree
        |      |                            |              |-bash---emacsclient
        |      |                            |              `-bash---ssh

ttyなんてコマンドも有ったな。 vmwareして起動し、ssh した場合。

vm$ tty
/dev/ttyp0

ソースはこんな所に有った。 /usr/src/usr.bin/tty/tty.c

t = ttyname(STDIN_FILENO);
if (!sflag)
        puts(t ? t : "not a tty");
exit(t ? 0 : 1);

wscons

前回目を付けてvt100のエミュレーションが動作するだろと思った奴が駄目だった。 少々悔しかったのでmanしたのさ。そしたら

NAME
     wscons - workstation console access

やっとwsの意味が判明。パソコンなのにワークステーションとはおそれ入った 名前だなあ。

Alt-Ctl-Fnでコンソールを切り替えられるようになってる。いわゆる仮想 コンソールだ。リナにも同様な機能が搭載されてるから当たり前の機能か。 まあ、普通の人はOS起動時からGUIに行ってしまうから、余り目にする事は 無いだろうけど。

qemu-kvmから使っているOpenBSD-i386 VGAな端末は表示しない設定で、起動時 からcom1画面を展開してる。

qe$ stty -a
speed 38400 baud; 34 rows; 0 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
        -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
        -extproc -xcase
iflags: -istrip icrnl -inlcr -igncr -iuclc ixon -ixoff ixany imaxbel
        -ignbrk brkint -inpck -ignpar -parmrk
oflags: opost onlcr -ocrnl -onocr -onlret -olcuc -oxtabs -onoeot
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
        eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
        min = 1; quit = ^\; reprint = ^R; start = ^Q; status = <undef>;
        stop = ^S; susp = ^Z; time = 0; werase = ^W;
qe$ echo $TERM
tmux

こんな風な確認は初めてだな。

qe$ sysctl -a | grep cons
kern.consdev=tty00
kern.consbufsize=16364
machdep.console_device=tty00
ddb.console=0

そして、これも初見だ。

qe$ doas wsconscfg 1
wsconscfg: screen 1 is already configured
qe$ doas wsconscfg 10
wsdisplay0: screen 10 added (80x25, vt100 emulation)

今、どんな設定になってるかも詳細にレポート出来るぞ。

te$ doas wsconsctl -a
keyboard.type=pc-xt
keyboard.bell.pitch=400
keyboard.bell.period=100
keyboard.bell.volume=50
keyboard.bell.pitch.default=400
keyboard.bell.period.default=100
keyboard.bell.volume.default=50
wsconsctl: Use explicit arg to view keyboard.map.
keyboard.repeat.del1=400
keyboard.repeat.deln=100
keyboard.repeat.del1.default=400
keyboard.repeat.deln.default=100
keyboard.ledstate=0
keyboard.encoding=us
mouse.type=ps2
mouse.reverse_scrolling=0
display.type=vga-pci
display.fontwidth=8
display.fontheight=16
display.emulations=vt100
display.screentypes=80x25,80x25bf,80x40,80x40bf,80x50,80x50bf
display.focus=0
display.screen_on=250
display.screen_off=0
display.vblank=off
display.kbdact=on
display.msact=on
display.outact=on

これを見る限り、VGAな端末上で動作する仮想端末では、vt100のエミュレーション 機能が動作すると思われる。

VGAな端末から操作すると、カーネルのそれなりの場所でブレークしたよ。雪辱を果た して大成功であります。

(gdb) bt 12
#0  wsemul_vt100_output_esc (edp=0xd0f1f2f0 <wsemul_vt100_console_emuldata>, instate=0xd0f1f3fc <wsemul_vt100_console_emuldata\
+268>) at /usr/src/sys/dev/wscons/wsemul_vt100.c:512
#1  0xd04187b2 in wsemul_vt100_output (cookie=0xd0f1f2f0 <wsemul_vt100_console_emuldata>, data=0xd23a6002 "H\033[J\033[3JI+pU \
    0:00.11 /usr/libexec/getty std.9600 ttyC5\r\n\n 10-100 startups (sshd)\r\ny secure Unix-like operating system.\r\n\r\nPlea\
se use the sendbug(1) utility to report bugs in the system.\r\nBefore re"..., count=8, kernel=0) at /usr/src/sys/dev/wscons/ws\
emul_vt100.c:1228
#2  0xd03908e3 in wsdisplaystart (tp=0xd23a3600) at /usr/src/sys/dev/wscons/wsdisplay.c:1534
#3  0xd075394c in ttstart (tp=0xd23a3600) at /usr/src/sys/kern/tty.c:1370
#4  0xd0756d3f in ttwrite (tp=0xd23a3600, uio=0xf0b5eda4, flag=1) at /usr/src/sys/kern/tty.c:1869
#5  0xd0391166 in wsdisplaywrite (dev=3072, uio=0xf0b5eda4, flag=1) at /usr/src/sys/dev/wscons/wsdisplay.c:1031
#6  0xd04d554b in spec_write (v=0xf0b5ecf0) at /usr/src/sys/kern/spec_vnops.c:302
#7  0xd038cb79 in VOP_WRITE (vp=0xd2295b00, uio=0xf0b5eda4, ioflag=1, cred=0xd2395e10) at /usr/src/sys/kern/vfs_vops.c:245
#8  0xd0346446 in vn_write (fp=0xd22fa964, uio=0xf0b5eda4, fflags=0) at /usr/src/sys/kern/vfs_vnops.c:408
#9  0xd0232cb4 in dofilewritev (p=0xd236d008, fd=1, uio=0xf0b5eda4, flags=0, retval=0xf0b5ee28) at /usr/src/sys/kern/sys_gener\
ic.c:380
#10 0xd0232aa3 in sys_write (p=0xd236d008, v=0xf0b5ee30, retval=0xf0b5ee28) at /usr/src/sys/kern/sys_generic.c:300
#11 0xd06be629 in mi_syscall (p=0xd236d008, code=<optimized out>, argp=<optimized out>, retval=<optimized out>, callp=<optimiz\
ed out>) at /usr/src/sys/sys/syscall_mi.h:179
(More stack frames follow...)

これを見ると、きっかけはユーザーランド側が発するwriteシステムコールって事だ。 このバックトレースを元に、提示されたファイルをトラバースしてくれるアプリを 作りたいぞ。どうもgdb中は落ち付いて閲覧するのを躊躇うってしまうからね。 本気で考えたいぞ。

tmux

コンソールってか端末を切り替える操作なら、何時もお世話になってるぞ。sshで リモート・ホストにログイン。して、ログイン先であたかも端末が複数存在するが ごとく振る舞う奴だ。これが表の顔だ。が、地味だけど、とっても嬉しい裏の顔も 存在してる。何かの拍子に接続が切れてしまっても、またログイン仕直して 再接続すれば、切断前の 状況に戻れる事。

人によっては、こちらの方が嬉しいかも知れない。リモートで作業開始。例えば OSのrelease(8)メディアを作成する場合とかだ。あんた勝手に作業を進めておいてね。 私は帰宅するから。こんな場合は、心情的にリモートとの切断を切ってしまいたい。 そして、翌朝、リモートに接続して、作業具合を確認するとかね。

これから、この興味深いtmuxを調べていきたいと思うけど、その前に少し下調べしとく。 linux sideでqemuを起動。リソースの割り当てを確認。

sakae@lu:~$ ps a | grep qemu
   3465 pts/3    Sl+    6:22 qemu-system-i386 -m 512 -nographic -no-fd-bootchk -s -net nic -net user,hostfwd=tcp::2022-:22 -hda disk
sakae@lu:~$ lsof -p 3465
 :
qemu-syst 3465 sakae    0u      CHR              136,3        0t0       6 /dev/pts/3
qemu-syst 3465 sakae    1u      CHR              136,3        0t0       6 /dev/pts/3
qemu-syst 3465 sakae    2u      CHR              136,3        0t0       6 /dev/pts/3
qemu-syst 3465 sakae    3u     IPv4              29382        0t0     TCP *:2022 (LISTEN)
qemu-syst 3465 sakae    4u  a_inode               0,15          0    3102 [eventfd:80]
qemu-syst 3465 sakae    5u  a_inode               0,15          0    3102 [signalfd]
qemu-syst 3465 sakae    6u  a_inode               0,15          0    3102 [eventfd:82]
qemu-syst 3465 sakae    7u  a_inode               0,15          0    3102 [eventfd:81]
qemu-syst 3465 sakae    8u      REG                8,2 4644143104 4610775 /var/my/qemu/qe/disk
qemu-syst 3465 sakae    9u     unix 0x0000000000000000        0t0   14952 type=STREAM (CONNECTED)
qemu-syst 3465 sakae   10u     unix 0x0000000000000000        0t0   14953 type=STREAM (CONNECTED)
qemu-syst 3465 sakae   11u     unix 0x0000000000000000        0t0   15791 type=STREAM (CONNECTED)
qemu-syst 3465 sakae   12u     unix 0x0000000000000000        0t0   15792 type=STREAM (CONNECTED)
qemu-syst 3465 sakae   13u     IPv4              29386        0t0     TCP *:1234 (LISTEN)
qemu-syst 3465 sakae   14u     IPv6              29387        0t0     TCP *:1234 (LISTEN)
qemu-syst 3465 sakae   21r  a_inode               0,15          0    3102 inotify

OpenBSD sideは、端末起動時、tty00だった。そこからtmuxを起動して、2つのkshを 動作させた。サーバーの配下でkshは動作してる。

qe$ pstree
-+= 00001 root /sbin/init
 |--= 10384 root sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)
 |-+= 65817 sakae tmux: server (/tmp/tmux-1000/default) (tmux)
 | |--= 91425 sakae -ksh (ksh)
 | \-+= 12331 sakae -ksh (ksh)
 |   \-+= 23918 sakae pstree
 |     \-+- 82513 sakae sh -c ps -kaxwwo user,pid,ppid,pgid,command
 |       \--- 93163 sakae ps -kaxwwo user

pstreeのCUI版でも確認。

qe$ ps xj
USER       PID  PPID  PGID     SESS JOBC STAT   TT       TIME COMMAND
sakae    65817     1 65817        0    0 Sp     ??    0:11.43 tmux: server (/tm
sakae    91425 65817 91425        0    0 I+p    p0    0:00.55 -ksh (ksh)
sakae    12331 65817 12331        0    0 Sp     p1    0:00.63 -ksh (ksh)
sakae    88446 12331 88446        0    1 R+pU   p1    0:00.03 ps -xj
sakae    95525     1 95525        0    0 Ip     00    0:00.57 -ksh (ksh)
sakae    41126 95525 41126        0    1 I+p    00    0:00.29 tmux: client (/tm

fstatはリナのlsofに相当する(情報量は違うけど)。

qe$ fstat -p 12331
USER     CMD          PID   FD MOUNT        INUM  MODE         R/W    SZ|DV
sakae    ksh        12331 text /          959059  -r-xr-xr-x     r   706784
sakae    ksh        12331   wd /         1036801  drwxr-xr-x     r      512
sakae    ksh        12331    0 /          416487  crw--w----    rw    ttyp1
sakae    ksh        12331    1 /          416487  crw--w----    rw    ttyp1
sakae    ksh        12331    2 /          416487  crw--w----    rw    ttyp1
sakae    ksh        12331   10 /          417149  crw-rw-rw-  rwep      tty
qe$ tty
/dev/ttyp1

ttyコマンドは、ちゃんと動作してるな。

裏の顔の確認

急に端末が切れたをやってもいいんだけど、それじゃあんまりなんで tmux detach で、自主的に切ってみる。

tmuxして起動。時間がかかるコンパイルを実施。その間に2番目の端末で起動 状態を確認。そしてdetach

te$ ps awx | grep tmux | grep -v grep
13012 ??  Sp       0:01.10 tmux: server (/tmp/tmux-1000/default) (tmux)
77164 p0  I+p      0:00.12 tmux: client (/tmp/tmux-1000/default) (tmux)
te$ tmux detach

tmuxのステータス・バーは消失した。けど、コンパイルは継続されてる。

te$ tmux
[detached (from session 0)]
te$ ps a
  PID TT  STAT        TIME COMMAND
66096 p0  Sp       0:00.05 -ksh (ksh)
21598 p0  R+pU     0:00.01 ps -a
43628 p1  S+p      0:00.24 -ksh (ksh)
53694 p2  Ip       0:00.12 -ksh (ksh)
74956 p2  S+p      0:00.16 make
48787 p2  R+       0:00.55 cc -g -O0 -I/usr/src/usr.bin/tmux -Werror-implicit-f
te$ ps awx | grep tmux | grep -v grep
13012 ??  Ip       0:01.25 tmux: server (/tmp/tmux-1000/default) (tmux)
te$ tmux attach

アッタッチすると、再びステータス・ラインが出現。

 :
cc   -o tmux alerts.o ... -lutil -lcurses -levent -lm
te$ ps awx | grep tmux | grep -v grep
13012 ??  Sp       0:01.49 tmux: server (/tmp/tmux-1000/default) (tmux)
24090 p0  I+p      0:00.09 tmux: client (/tmp/tmux-1000/default) (tmux)

コンパイルは無事に完了してた(記録が残る、ありがたい仕様)。そしてtmux clientは新たに創成されてた。 serverの方はそのまま鎮座してた。このserverが消えるのは、tmuxで起動してる アプリ(通常はshell)が全て終了した時だ。

なお、このtmuxはOpenBSDの標準配布物になってる。昔、そんな事を知らないオイラーは GNU screenを使ってた。余計な物は入れるな主義なんでtmuxに乗り換えた経緯がある。 何と言ってもソースが目の前に有る安心。そして現在もたぬまぬ拡張が続いている。 OpenSSHやらLibresslと同様に大事にメンテナンスされてる証拠。これはもう見るしかないね。

README

昭和歌謡界隈の歩き方

ポップな表紙につられて手に取ってみた。表紙のオネーさんは誰? ちょいと気に なるぞ。ちあきなおみの '喝采' とか、奥村チヨさんの '終着駅' を絶賛されて たから、このどちらかだろう。ああ、なおみさんだった。

先生の勧めで YouTube を聞いてみた。昭和歌謡メドレー とかで検索すると山の ように出てくる。著作権大丈夫か??

アメリカン・フィーリング サーカス これならJALのCMソングだったから大丈夫だな。 懐かしい曲だな。


This year's Index

Home