exceptコマンドと端末サイズ変更のシグナル「SIGWINCH」

Page content

端末のサイズ変更が効かないときがあった

当初は自分なりの運用で回避

共用サーバを扱う上でありがちなのは、次のように、pcからserver1に一般ユーザ権限でSSHログインし、su -でrootパスワードを打って管理者権限にて行う作業です。これが一日に何度も必要な時、どうするか。

user@pc:~$ ssh server1
staff@server1:~$ su -
Password: rootのパスワード
root@server1:~# 

各コマンドやパスワードの対話的な手入力はexpectコマンドを使えば自動化できます。そこで私はこれまで、次のようなスクリプトでserver1へのログインとsu -をやっていました。

#!/bin/bash

expect -c "
	set timeout 30
	spawn ssh -t server1 \"LANG=C su -\"
	expect {
		\"Password:\" {
			send \"rootのパスワード\n\"
		}
		timeout { exit 1 }
	}
	interact
"

他方、私がserver1で管理者権限での作業を行っている時に限って? (「この時に限る」と今だから分かる)、端末 (ターミナル画面) のウィンドウのサイズ変更にlessコマンドやその他コマンドが追従しないという謎現象に遭遇してきました。

ふつうは追従するのが当たり前なのでこれは不便です。しかしどんな場合に発生して何が原因なのかを深く調べぬまま、端末のウィンドウを広げて謎現象で困った時は“端末を最初のサイズに手で戻す”という消極的な運用をして、不便を回避してきました。

SIGWINCHの役目

そんなある日、別件でLinuxのシグナルについて調べていて、次のページを開いた時に、SIGWINCHの文字が目に止まりました。端末のサイズ変更タイミングはいわゆるシグナルで伝わるんだ、と初めて知った瞬間です。

名前番号動作意味
SIGWINCH28Ignoreウィンドウのサイズが変更された

ということは、いつも困っているあの謎現象はこのシグナルが関係しているのかもと気付きます。次のページに掲載されている、SIGWINCHシグナルをトラップして端末サイズを都度表示するスクリプトsigwinch_trap.shを用いて問題の切り分けを試みますと、

上記のお手製expectコマンドでログインしている状態のserver1の環境では、SIGWINCHシグナルを感知していないことが判明。なるほど、謎現象の原因が見えてきました。

SIGWINCHを処理するようにexpectを書こう

問題の原因が分かると、解決法をGoogle先生に尋ねやすくなります。今回の件は先人の知恵を借りますと、exceptを用いるログイン時に、trapで始まりWINCHで終わる5行を次のように加えると、SIGWINCHシグナルをexpectコマンドがうまく処理するようになると分かりました。

#!/bin/bash

expect -c "
	trap {
		set rows [stty rows]
		set cols [stty columns]
		stty rows \$rows columns \$cols < \$spawn_out(slave,name)
	} WINCH
	set timeout 30
	spawn ssh -t server1 \"LANG=C su -\"
	expect {
		\"Password:\" {
			send \"rootのパスワード\n\"
		}
		timeout { exit 1 }
	}
	interact
"

まとめ

以上、expectでログイン中の環境に、端末のサイズ変更で発せられるSIGWINCHシグナルを伝える方法の紹介でした。ウェブ上ではもう新鮮味のない情報ですが、私としては、問題の原因を調べるプロセスも含めて面白かったのでメモとして記録です。

また、上記のスクリプトでは「rootのパスワード」とサラッと書いてきた、本来は暗号化して扱いたい秘匿情報をスクリプトなどにどう保存しておくかは、別途書きました次の記事が参考になるかもしれません。

参考リンク