汎用的な製品を組み合わせて格安で継続的に利用できるシリアルコンソールサーバの構築を検討する。
完成イメージはこんな感じ

USBポート位置とデバイス名の紐付け
通常何も設定しなければデバイス名は指した順番に /dev/ttyUSB0 ... USB1 ... USB2 という風に生成されていくが、これではどのポートのデバイスがどんなデバイス名かが固定されず、故障交換の都度デバイス名が変更されコンソールサーバツールの設定を都度見直す必要が出てきてしまうため、これをUSBのポート(USBハブを想定)とKERNELSの接続位置ポート名(Alias名もしくはSymlink名)を紐付けて固定する。
USBポート位置の確認
udevadmコマンドによりKERNELSの値を確認し位置を確認する。
root@catalyst:~# udevadm info -a -n /dev/ttyUSB0 |egrep "(KERNELS|DEVPATH)"
KERNELS=="ttyUSB0"
KERNELS=="1-1.3:1.0"
KERNELS=="1-1.3"
KERNELS=="1-1"
KERNELS=="usb1"
KERNELS=="0000:00:14.0"
KERNELS=="pci0000:00"
root@catalyst:~# udevadm info -a -n /dev/ttyUSB1 |egrep "(KERNELS|DEVPATH)"
KERNELS=="ttyUSB1"
KERNELS=="1-1.4:1.0"
KERNELS=="1-1.4"
KERNELS=="1-1"
KERNELS=="usb1"
KERNELS=="0000:00:14.0"
KERNELS=="pci0000:00"
root@catalyst:~# udevadm info -a -n /dev/ttyUSB2 |egrep "(KERNELS|DEVPATH)"
KERNELS=="ttyUSB2"
KERNELS=="1-3:1.0"
KERNELS=="1-3"
KERNELS=="usb1"
KERNELS=="0000:00:14.0"
KERNELS=="pci0000:00"
位置とデバイス名をAlias(Symlink)によって固定
vi /etc/udev/rules.d/99-usb-serial.rules
SUBSYSTEM=="tty", KERNELS=="1-1.3.1.0", SYMLINK+="ttyUSB01", MODE="0666"
SUBSYSTEM=="tty", KERNELS=="1-1.4.1.0", SYMLINK+="ttyUSB02", MODE="0666"
SUBSYSTEM=="tty", KERNELS=="1-3.1.0", SYMLINK+="ttyUSB03", MODE="0666"
idVendorや、idProductは特に指定しなくてもよくて、KERNELSでの接続位置に対してポート名となるSYMLINKを割り当てたい。というのは、故障交換時に別の製品をつかったりする事もあるだろうから、接続位置情報とデバイス名を紐づけて変化しないようにする。
ここでは3ポートを想定しています。もっと沢山繋ぐ場合は、ポートの場所を調べてKERNELSに登録してSYMLINKでわかりやすいデバイス名にするようにしてください。
設定の反映
% sudo udevadm control --reload-rules
% sudo udevadm trigger
確認
root@catalyst:~# ls -l /dev/ttyUSB*
crw-rw---- 1 root dialout 188, 0 9月 5 01:00 /dev/ttyUSB0
lrwxrwxrwx 1 root root 7 9月 5 01:00 /dev/ttyUSB01 -> ttyUSB0
lrwxrwxrwx 1 root root 7 9月 5 01:00 /dev/ttyUSB02 -> ttyUSB1
lrwxrwxrwx 1 root root 7 9月 5 01:00 /dev/ttyUSB03 -> ttyUSB2
crw-rw---- 1 root dialout 188, 1 9月 5 01:00 /dev/ttyUSB1
crw-rw---- 1 root dialout 188, 2 9月 5 01:00 /dev/ttyUSB2
コンソールサーバとその機能
パッケージのインストール
% sudo apt install conserver-server conserver-client xinetd
xinetdは、SmartCSをまねる際に使います。クライアントからconserver-clientでサーバの3109ポートに接続する方法の場合は不要です。
conserver-serverでは、logfileを指定しておくと接続していない間のコンソールの出力も保存しておくことが出来ます。不慮の再起動の際に出力されたコンソールのメッセージなど調査の際に有効であるケースもあるためうれしい機能です。
今回は3ポートだけUSBシリアルの設定を入れております。本件通してポートは3つで実際に試しながらこの記事を書いております。
- /etc/conserver/conserver.cf
console com1 {
master localhost;
type device;
device /dev/ttyUSB01;
baud 9600;
parity none;
logfile /var/log/conserver/com1.log
timestamp 1;
}
console com2 {
master localhost;
type device;
device /dev/ttyUSB02;
baud 9600;
parity none;
logfile /var/log/conserver/com2.log
timestamp 1;
}
console com3 {
master localhost;
type device;
device /dev/ttyUSB03;
baud 9600;
parity none;
logfile /var/log/conserver/com3.log
timestamp 1;
}
access * {
trusted 127.0.0.1;
allowed 127.0.0.1;
}
ひとまずコンソールを3ポートとしています。デバイス名はSYMLINKで作った方を指定しています。
設定を反映するためconserverをreloadします。
% sudo service conserver-server restart
% sudo service conserver-server status
通常の利用
conserver-serverをインストールすると、TCP3109番ポートがListen状態になり、そのポートにtelnetではなく、conserver-clientパッケージのconsoleコマンドを使ってどのコンソールサーバのどのポートに接続するかを指定して繋ぐという利用のが通常の利用方法のようです。

操作用PCをPC1、コンソールサーバをPC2、例の設定の通りUSBシリアルは、com1, com2, com3 と設定している場合。
PC1にはconserver-clientをインストールしている必要があります。
PC2は
PC1端末で以下のように実行すれば、コンソールサーバであるPC2のcom1につながっている装置に接続できます。
% console -M PC2 com1
SmartCSっぽい使い方
今回はポート数を3つとしておりますが、USB-HUBなどを用いていくらでも(127が上限?)必要な数設定可能です。USB-HUBは外部から電源を供給するタイプで無いとPCからだけでは足りなくなると思いますのでご注意。
セイコーさまの、SmartCSというコンソールサーバでは、LISTENするポート番号を「8100 + ポート番号」と、接続先のポートとを紐づけしており、クライアントはtelnetで繋ぐことが出来ます。conserverでも、xinetdを組み合わせれば出来そうなのでやってみます。
また、この方法はxinetdがconserver-clientのconsoleコマンドを実行するため、サーバ側にもclientパッケージをインストールする必要があります。(最初にインストールしているのでここでは手順を省略します。)

serviceへのポート追加
- /etc/services
com1 8101/tcp # conserver-server
com2 8102/tcp # conserver-server
com3 8103/tcp # conserver-server
xinetdの設定
- /etc/xinetd.d/servers
service com1
{
type = UNLISTED
port = 8101
socket_type = stream
protocol = tcp
wait = no
disable = no
user = nobody
group = nogroup
server = /usr/bin/console
server_args = com1
log_on_failure += USERID
log_on_success += USERID
}
service com2
{
type = UNLISTED
port = 8102
socket_type = stream
protocol = tcp
wait = no
disable = no
user = nobody
group = nogroup
server = /usr/bin/console
server_args = com2
log_on_failure += USERID
log_on_success += USERID
}
service com3
{
type = UNLISTED
port = 8103
socket_type = stream
protocol = tcp
wait = no
disable = no
user = nobody
group = nogroup
server = /usr/bin/console
server_args = com3
log_on_failure += USERID
log_on_success += USERID
}
設定の反映
% sudo service xinetd restart
% sudo service xinetd status
接続テスト
コンソールサーバ上で自分自身に接続して試してみます。com1の先に何も繋いで無いのでdownと出ていますが、com1が選択されconsoleコマンドが実行されているのがわかります。
% telnet localhost 8101
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'
['com1' -- console is down]
[Enter '^Ec?' for help]
telnetのエスケープと、xinetdから呼ばれたconsoleコマンドのエスケープが被ってしまって、consoleのエスケープが上手く反応させられないのですが、ちょっと調べてみます… orz...
ひとまず、telnetの替わりにncコマンドを用いるとエスケープは反応してくれるようですが、^Ec の入力後 ] が出ないので反応してくれているか見てわかりません…
クライアントにconsoleコマンドを入れるというのが現実的ではない為、クライアントでは汎用的なtelnetなどで繋がるのが理想ですよね。
WEB-UIの開発
コンソールサーバとして必要な値として以下のようなものがあります。これらの値についてはサーバにログインして設定ファイルを直接編集するというのもありなのですが、管理用のWEB-UIなどを用意する方が利便性がよさそうです。
- ホストの設定
- サーバのホスト名
- サーバのIPアドレスとマスクとデフォルトゲートウェイ
- サーバへのアクセス制御
- アカウント管理
- NTP
- SNMP
- ログの保存期間
- ポートの設定
- 通信速度(デフォルト 9600 Baud? bps?)
- パリティ
- ストップビット
- ポート数の増減
- ログの閲覧