ゲストOSの起動ログをvmplayerに依存せずに見る方法

■ゲストOSの起動ログをvmplayerに依存せずに見る方法

 vmplayerに設定すればシリアルコンソール接続で起動ログは見れる。
 vmplayerに設定せずにTCP接続でも起動ログは見れる。

 socatを使って「kern.log」をTCP4で待ち受けるようにすると、
 Virtualbox用とか、QEMU用とかXen用とか関係無く、
 ゲストOSの起動ログをホスト側で見ることが出来ます。

 【制限】
  ネットワークとsocatは常に実行可能であることが前提。
   ※その前に落ちるようなデバッグ用途には使えない。
  起動時は「rc.local」の実行がされるまで見れない。
  終了時、再起動時は「rc.local」のストップが呼び出されるまで見れる。

 「range」を使ってアドレス範囲の制限をしていますが、
 「host-only」の「vmnet1」に接続しているので、どの道見れるのはホストOSのみですが、
 「iptables」で破棄ルールを設定しても、「namp」コマンドで「vmnet8」側でも待ち受けているように見えてしまいます。

$ netstat -an | grep 8082 | grep -v 172
tcp        0      0 0.0.0.0:8082            0.0.0.0:*               LISTEN

$ sudo nmap -sT -p 8082 192.168.164.177 | grep ^8082
8082/tcp filtered blackice-alerts

■vmplayerの場合

 VMwarePlayerで、Lenny on Lenny シリアルコンソール接続
 http://d.hatena.ne.jp/labunix/20120214

 VMwarePlayerで、Squeeze on Squeeze シリアルコンソール接続
 http://d.hatena.ne.jp/labunix/20120215

■対象は「dmesg」コマンドか、ログの「kern.log」か「syslog」。

$ sudo grep "syslog\$\|^kern" /etc/rsyslog.conf
*.*;auth,authpriv.none          -/var/log/syslog
kern.*                          -/var/log/kern.log

■socatをまだインストールしていないなら。。。

$ dpkg -l socat | grep ^ii || sudo apt-get install -y socat

■クライアント側の「rc.local」にsocatコマンドを埋め込む。

$ grep socat /etc/rc.local
/usr/bin/socat file:/var/log/kern.log TCP4-LISTEN:8082,fork,range=192.168.0.0/24

■ホスト側の待ち受け方法
 ※rc.localが実行されてsocatが実行されたタイミングで表示出来る。
  ネットワーク設定とsocatの実行が前提。

$ GUESTIP="192.168.32.177"
  while true ;do socat OPEN:vmkern.log,create tcp4:${GUESTIP}:8082,fork;sleep 2;done
$ sudo tail -f vmkern.log

■シリアルコンソールと同様の見栄えに加工する。
 ついでにページャにパイプして、速すぎて見えないなんてことにならないようにする。

$ sed s/".*kernel\: "//g vmkern.log | less


■以下、おまけ。

□dmesgか、syslogを使う場合

$ sudo dmesg > dmesg.log

 ※upの後ろは1時間16分経過していることを示す。

$ uptime | awk -F\, '{print $1}'
 19:45:12 up  1:16

$ sudo cat /var/log/syslog | grep "kernel\: \[" | \
  grep "`env LANG=C date | cut -c 5-11`" | \
  sed s/".*kernel\: "//g > dmesg.log.1

$ diff -s dmesg.log dmesg.log.1
ファイルdmesg.logとdmesg.log.1は同一

 ※upの前は実行時間

$ date '+ %H:%M:%S';uptime | awk -F\, '{print $1}'
 19:48:17
 19:48:17 up 19 days

□socatのオプション

$ man socat | grep -A 2 "TCP4.*\:<port>\$"
       TCP4:<host>:<port>
              Like TCP, but only supports IPv4 protocol (example).
              Option groups: FD,SOCKET,IP4,TCP,RETRY
--
       TCP4-LISTEN:<port>
              Like TCP-LISTEN, but only supports IPv4 protocol (example).
              Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP4,TCP,RETRY

$ man socat | grep -A 2 "reuseaddr\$"
       reuseaddr
              Allows  other  sockets to bind to an address even if parts of it
              (e.g. the local port) are already in use by socat (example).

$ man socat | grep -A 7 "fork *After"
       fork   After  establishing a connection, handles its channel in a child
              process and keeps the parent process attempting to produce  more
              connections,  either  by  listening  or  by connecting in a loop
              (example).
              OPENSSL-CONNECT and SSL-LISTEN differ in when they actually fork
              off  the  child:  OPENSSL-LISTEN forks before the SSL handshake,
              while  OPENSSL-CONNECT  forks  afterwards.   RETRY  and  FOREVER
              options are not inherited by the child process.

$ man socat | grep -A 7 " OPEN\:<filename>"
       OPEN:<filename>
              Opens <filename> using the open() system call  (example).   This
              operation fails on UNIX domain sockets.
              Note: This address type is rarly useful in bidirectional mode.
              Option groups: FD,REG,NAMED,OPEN
              Useful  options: creat, excl, noatime, nofollow, append, rdonly,
              wronly, lock, readbytes, ignoreeof
              See also: CREATE, GOPEN, UNIX-CONNECT

□STDINで受け取る場合(サーバ==クライアント)

 ※サーバ側

$ netstat -an | grep "\:8081" | wc -l
0
$ socat TCP4-LISTEN:8081,fork,reuseaddr STDIN

 ※クライアント側

$ dmesg > dmesg.log
$ socat OPEN:dmesg.log TCP4:localhost:8081


□「8081」の入力を「/dev/pts/1」に転送する。(サーバ==クライアント)

 ※サーバ側

$ sudo socat TCP4-LISTEN:8081,fork /dev/pts/1

 ※クライアント側
$ socat OPEN:dmesg.log TCP4:localhost:8081

□ファイルで受け取る場合(サーバ!=クライアント)

 ※サーバ側(受け取ったらCtrl+Cで終了)

$ socat TCP4-LISTEN:8081,fork,reuseaddr OPEN:dmesg.log.2,create
^C

 ※クライアント側

$ HOSTIP="192.168.0.5"
  socat OPEN:dmesg.log TCP4:${HOSTIP}:8081

$ wc -l dmesg.log*
  1103 dmesg.log
   738 dmesg.log.1
  1103 dmesg.log.2
  2944 合計

□dmesgは、rootで受け取りたい。(サーバ!=クライアント)

$ sudo socat TCP4-LISTEN:8081,fork,reuseaddr OPEN:dmesg.log.2,user=root,group=root,mode=0400,create
^C

$ HOSTIP="192.168.0.5"
  socat OPEN:dmesg.log TCP4:${HOSTIP}:8081
$ ls -l dmesg.log.2
-r-------- 1 root root 69806 2013-01-19 20:24 dmesg.log.2