タグ別アーカイブ: Linux

ふと思ったこと: smbclientを使ってWindowsの共有フォルダへアクセス

Windows上の共有フォルダにLinuxクライアントからアクセスします。
smbclientが便利です。

WIndows側の設定
① 共有フォルダの作成

② テストのために共有フォルダのしてにtest.txtをおいておく

Linux側の設定
③ smb-clientをインストール
# yum install samba-client

④ smbclientコマンドを使って、WIndowsの共有フォルダへアクセス
smbclient ‘\WindowsのIPアドレス共有フォルダ’
        例) smbclient ‘\192.168.11.4tmp’

enter root’s password: ← 共有フォルダのパスワードをいれる                
Domain=[SHINDOWSXP] OS=[Windows 5.1] Server=[Windows 2000 LAN Manager]
smb: >

⑤ get を使って、test.txtをコピー
smb: > get test.txt

getting file test.txt of size 12 as test.txt (0.5 KiloBytes/sec) (average 0.5 KiloBytes/sec)  

(Linux)CentOSからWindows共有をマウントする方法 : 3流プログラマのメモ書き

現在下記のようなサーバを構築してます。
CentOSサーバ Windowsサーバ
FTP–>Win共有フォルダマウントポイント——>Windowsファイル共有してるフォルダ

要はFTPを経由してLAN内のファイルサーバとして使ってるWindowsマシンの共有フォルダを見たいわけです。

ちなみにFW使ってる場合はポートの445の解放が必要です。

ここを見るとsmbmount コマンドでできるとあったのですが、そんなコマンドはないと怒られます。どうやらCentOS5にはこのコマンドはなくなったようです。
mountコマンドでCIFSをファイル共有

Parallel sshで複数のホストへ同時にコマンドを実行する | Glide Note – グライドノート

pssh
pssh(Parallel ssh)とは、複数のホストに対して同じ処理が実行できる並行処理型のSSHツールです。psshには平行処理形で複数のホストにscp、rsyncが実行出来るpscp、prsync、複数のホストから一斉にファイルを収集するpslurpが含まれています。

使い方がシンプルなので複数のホストに同じ処理を実行したい場合に便利です。
導入環境はCentOS5.5です。

psshの導入

psshの導入にsetuptoolsが必要なのでyumで導入

sudo yum -y install python-setuptools

最新版のpsshを導入。2010/08/26現在の最新バージョンは2.1.1です。

mkdir ~/tmpcd ~/tmpwget http://parallel-ssh.googlecode.com/files/pssh-2.1.1.tar.gztar zxvf pssh-2.1.1.tar.gzcd pssh-2.1.1sudo python setup.py install

pssh(pscp、prsync、pslurp)を利用するには

  • psshを実行するサーバから各ホストにssh鍵が通してある
  • psshで指定するユーザ(-lオプションで指定するユーザ)が各ホストに存在し、ssh接続が可能である。

が必要になります。

pssh 複数のホストで一斉に同じ処理をする

簡単な利用方法は下記のような形で

pssh -h {リストファイル名} -l {コマンドを実行するユーザ名} -i {コマンド}

psshの主要なオプションは下記のとおりです。

オプション-h ホストを記載したリストファイルを指定-l リモートでコマンドを実行するユーザ-p sshのポート番号を指定(指定しない場合はデフォルトの22番を利用)--timeout コマンドのタイムアウト時間を指定(デフォルトは60秒)

-h で指定するリストファイルは下記のような形になっています。ローカル環境なのでglidenote.lanを指定。

[akira@manage][0] $ cat db_server_list.txtm-db001.glidenote.lans-db001.glidenote.lans-db002.glidenote.lans-db003.glidenote.lans-db004.glidenote.lan

psshを利用してuptimeコマンドを一斉に実行した際の結果

[akira@manage][0] $ sudo pssh -h db_server_list.txt -l root -i "uptime" [1] 18:49:04 [SUCCESS] m-db001.glidenote.lan 18:49:04 up 30 days,  6:47,  1 user,  load average: 0.91, 0.67, 0.56[2] 18:49:04 [SUCCESS] s-db001.glidenote.lan 18:49:04 up 26 days,  7:00,  2 users,  load average: 0.36, 0.27, 0.24[3] 18:49:04 [SUCCESS] s-db004.glidenote.lan 18:49:04 up 26 days,  6:51,  2 users,  load average: 0.00, 0.02, 0.00[4] 18:49:04 [SUCCESS] s-db003.glidenote.lan 18:49:04 up 26 days,  6:54,  1 user,  load average: 0.26, 0.25, 0.20[5] 18:49:04 [SUCCESS] s-db002.glidenote.lan 18:49:04 up 26 days,  6:57,  0 users,  load average: 0.20, 0.26, 0.26

s-db005.glidenote.lan,s-db006.glidenote.lanという存在しないホストをリストに
登録すると下記のように[FAILURE]と返ってきます。

[akira@manage][0] $ sudo pssh -h db_server_list.txt -l root -i "uptime"                                                                                 [~][1] 18:50:31 [FAILURE] s-db005.glidenote.lan Exited with error code 255[2] 18:50:31 [FAILURE] s-db006.glidenote.lan Exited with error code 255[3] 18:50:31 [SUCCESS] m-db001.glidenote.lan 18:50:31 up 30 days,  6:48,  1 user,  load average: 0.60, 0.61, 0.54[4] 18:50:31 [SUCCESS] s-db001.glidenote.lan 18:50:31 up 26 days,  7:02,  2 users,  load average: 0.66, 0.36, 0.27[5] 18:50:31 [SUCCESS] s-db002.glidenote.lan 18:50:31 up 26 days,  6:58,  0 users,  load average: 0.15, 0.23, 0.25[6] 18:50:31 [SUCCESS] s-db003.glidenote.lan 18:50:31 up 26 days,  6:55,  1 user,  load average: 0.26, 0.26, 0.21[7] 18:50:31 [SUCCESS] s-db004.glidenote.lan 18:50:31 up 26 days,  6:52,  2 users,  load average: 0.00, 0.02, 0.00

pscp 複数のホストのファイルを転送

scpコマンドを複数のホストの実行する形になります。puppetやデプロイツールを利用している場合は、あまり利用することはないかもしれません。利用方法は

pscp -h {リストファイル名} -l {コマンド実行ユーザ名}  {ローカルのファイルパス} {リモートのファイルパス}

実際のコマンドは下記のような形です。

sudo pscp -h db_server_list.txt -l glidenote /home/glidenote/hogehoge.txt /home/glidenote/hogehoge.txt

ディレクトリごとscpする場合は再帰的に処理するオプション –recursive を付加

sudo pscp -h db_server_list.txt --recursive -l glidenote /home/glidenote/hoge_dir /home/glidenote/

prsync 複数のホストとファイルを同期する

これもpscpと同様にpuppetやデプロイツールを利用している場合にはあまり利用しないかと思います。使い方は

prsync -h {リストファイル名} -l {コマンド実行ユーザ名} {ローカルパス} {リモートパス}

実際のコマンドは下記のようになります。

sudo prsync -h db_server_list.txt --recursive -l glidenote /hoge/akira/work /home/glidenote/remote_work

再帰的に処理する場合は –recursiveを付加

sudo prsync -h db_server_list.txt -l root -a --recursive  /home/akira/pscp_dir /root/tmp/

pslurp 複数のホストから一括でファイルを取得する

pslurpは複数のホストから一括でファイルを取得できるので、ログや設定ファイルを一斉に収集したい場合などに重宝します。

pslurp -h {リストファイル名} -l {コマンド実行ユーザ名} -L {ファイルを保存するローカルパス} -r {リモートパス} {ファイルを保存するディレクトリ名}

ホストごとにディレクトリが作成され、一番最後に指定する引数でディレクトリ名が生成されるので、ファイルも見やすく、トラブル時などは非常に便利です。

sudo pslurp -h db_server_list.txt -l root -L /home/akira/result -r /var/log/messages messages

実際ファイルを収集した際のディレクトリ構成

[akira@manage][0] $ ls -al /home/akira/resulttotal 28drwxr-xr-x  7 root  4096 Aug 24 18:07 .drwx------ 13 akira 4096 Aug 24 18:09 ..drwxr-xr-x  2 root  4096 Aug 24 18:07 m-db001.glidenote.landrwxr-xr-x  2 root  4096 Aug 24 18:07 s-db001.glidenote.landrwxr-xr-x  2 root  4096 Aug 24 18:07 s-db002.glidenote.landrwxr-xr-x  2 root  4096 Aug 24 18:07 s-db003.glidenote.landrwxr-xr-x  2 root  4096 Aug 24 18:07 s-db004.glidenote.lan

ホストごとにディレクトリが生成されて、設定が確認しやすいです。

[akira@manage][0] $ ls -R /home/akira/result/home/akira/result:m-db001.glidenote.lan  s-db001.glidenote.lan  s-db002.glidenote.lan  s-db003.glidenote.lan  s-db004.glidenote.lan /home/akira/result/m-db001.glidenote.lan:messages /home/akira/result/s-db001.glidenote.lan:messages /home/akira/result/s-db002.glidenote.lan:messages /home/akira/result/s-db003.glidenote.lan:messages /home/akira/result/s-db004.glidenote.lan:messages

pnuke 複数のホストで同時にプロセスをkillする

条件に一致したプロセスを一斉にpkill -9するpnukeというコマンドもpsshに含まれていますが、
psshで代用が出来るとの、これまでの経験でそういったことが必要だったことがないので利用していません。

ドキュメントが少ないの(pythonなので何をしているかは読めば分かりますが)と、エラー時に簡単なログしか吐かなかったりするので原因が掴みにくい部分がありますが、使い方は非常にシンプルなので、

  • 一斉にサーバのステータスを知りたい時
  • トラブル時に全台に同じコマンドを実行したい場合
  • 全台からログを収集したい場合

など非常に便利です。
非常に便利なコマンドですが、一斉に全ホストに処理が実行されるので、必ずテスト用サーバを数台だけ記載したリストファイルを用意し、問題がなければ全台に適用などを行った方がいいです。

複数のサーバから一斉にファイルを収集するのにpslurpが便利 – Glide Note – グライドノート

以前、ブログに書いて以来、活用しているpsshpscpなんですが、付属コマンドのpslurpについてはすっかり忘れて全く利用していなかったんですが、同僚の刺身さんが結構活用しているというのを聞いて、改めて使ってみると大変便利!

環境はSL6.1です。

pslurpの使いどころ

  • 複数のサーバからaccess.logなどのログ、my.cnfといった設定ファイルなどの同名ファイルを持ってくる場合
  • DNSラウンドロビンや、ロードバランサを利用していてアクセスログが分散している場合

通常何も考えずscpとかで持ってくるとファイルが上書きされてしまうので、ホスト毎にファイルを分けて管理したい場合にpslurpが活躍します。

pipを利用してpsshの導入

2012年なんでeasy_installではなく、pipを利用して導入。

1
sudo pip install pssh

接続先のサーバリストの作成

db_server.txtとかで下記のようなファイルを用意。各ホストには鍵が通っている必要があります。

12345678910
mysql0.glidenote.lanmysql1.glidenote.lanmysql2.glidenote.lanmysql3.glidenote.lanmysql4.glidenote.lanmysql5.glidenote.lanmysql6.glidenote.lanmysql7.glidenote.lanmysql8.glidenote.lanmysql9.glidenote.lan

ファイルの一斉取得

下記のようなコマンドでファイルを一斉に取得

12
sudo pslurp -h db_server.txt /etc/my.cnf .sudo pslurp -h db_server.txt /var/log/secure .

下記のようにホスト毎にディレクトリが作られて、ファイルが収納される。

123456789101112131415161718192021222324252627282930313233
[akira@manage] $ tree.|-- db_server.txt|-- mysql0.glidenote.lan|   |-- my.cnf|   `-- secure|-- mysql1.glidenote.lan|   |-- my.cnf|   `-- secure|-- mysql2.glidenote.lan|   |-- my.cnf|   `-- secure|-- mysql3.glidenote.lan|   |-- my.cnf|   `-- secure|-- mysql4.glidenote.lan|   |-- my.cnf|   `-- secure|-- mysql5.glidenote.lan|   |-- my.cnf|   `-- secure|-- mysql6.glidenote.lan|   |-- my.cnf|   `-- secure|-- mysql7.glidenote.lan|   |-- my.cnf|   `-- secure|-- mysql8.glidenote.lan|   |-- my.cnf|   `-- secure`-- mysql9.glidenote.lan    |-- my.cnf    `-- secure

同じようなことをシェルスクリプトでやろうとするとディレクトリ作ったりとか下記のような感じで面倒くさい。

12345678910111213141516171819202122232425262728
#!/bin/sh

SERVERS=
mysql0.glidenote.lan
mysql1.glidenote.lan
mysql2.glidenote.lan
mysql3.glidenote.lan
mysql4.glidenote.lan
mysql5.glidenote.lan
mysql6.glidenote.lan
mysql7.glidenote.lan
mysql8.glidenote.lan
mysql9.glidenote.lan

FILES=
/var/log/secure
/etc/my.cnf

for server in ${SERVERS};
do
mkdir ${server}
    for file in ${FILES}
    do
scp ${server}:${file} ${server}/
    done
done
view raw getfile.sh This Gist brought to you by GitHub.

<pre><code>#!/bin/shSERVERS=&quot;mysql0.glidenote.lanmysql1.glidenote.lanmysql2.glidenote.lanmysql3.glidenote.lanmysql4.glidenote.lanmysql5.glidenote.lanmysql6.glidenote.lanmysql7.glidenote.lanmysql8.glidenote.lanmysql9.glidenote.lan&quot;FILES=&quot;/var/log/secure/etc/my.cnf&quot;for server in ${SERVERS};do mkdir ${server} for file in ${FILES} do scp ${server}:${file} ${server}/ donedone</code></pre>

特定の日時のログを一括で確認したい場合や、サーバ全台の設定ファイルの比較とかに活用出来ます。

ファイルのデプロイに関してはpuppetやwebistranoなどで管理が出来ていますが、ファイルの一斉収集についてはpslurpが良い感じですね。

Stowを利用してソースからビルドしたソフトウェアを効率的に管理する – Glide Note – グライドノート

同じチームの@lamanotramaさんと話していて、これから一部パッケージはRPMを作らず、@hirose31さんの方式(ソースから自前ビルドしたソフトウエアの効率的な管理方法 – (ひ)メモ)を採用するとのことで、「なるほど!!」と思いながら上記記事のはてブコメントを眺めてたらStowというものを発見。

早速検証してみた。検証環境はCentOS 6.3です。

Stowの概要

  • Perlで書かれている
  • ソースからビルドしたソフトウェアを管理するソフト
  • 任意のディレクトリ/usr/local/stowなどにパッケージ一式をインストール
  • インストールしたパッケージから/usr/lib/{bin,lib,share}にリンクを貼って利用。
  • バージョンの切り替えはリンク張り直しで行う(ファイルの上書きはしない)
  • zsh-4.3.17zsh-5.0.0などバージョンの切り替えが容易になる(同じようなソフトのpacoと違う点)

Stowの導入

epelにあるのでyumで導入。cpanmでも入ります。

1
sudo yum -y install stow

Stow用のディレクトリを用意

パッケージインストール用のディレクトリを作成

1
sudo mkdir -p /user/local/stow/

Stowを利用してzsh-5.0.0を導入

試しにzsh-5.0.0を利用してみる。

configureのときに--prefix=/usr/local/stow/zsh-5.0.0といった感じで、--prefix=/usr/local/stow/{name}-{version}というような感じでインストール先を指定し、/usr/local/stow/以下に一式インストールする。これにより/usr/local/{bin,lib,share}以下が汚れずに済むし、管理も楽になる。

12345678
mkdir ~/srccd ~/srccurl -Lo zsh-5.0.0.tar.gz http://sourceforge.net/projects/zsh/files/zsh/5.0.0/zsh-5.0.0.tar.gz/downloadtar zxvf zsh-5.0.0.tar.gzcd zsh-5.0.0./configure --prefix=/usr/local/stow/zsh-5.0.0makesudo make install

stowコマンドを用いて、/usr/local/{bin,lib,share}にsymlinkを貼る。-v,--verboseをつけると詳細が見えるので良い感じです。

12
cd /usr/local/stowsudo stow -v zsh-5.0.0

symlinkを貼ろうとした際に既にファイルが存在すると下記のようなエラーが発生する。

12345
[akira@dev001] $ sudo stowWARNING! stowing bin would cause conflicts:  * existing target is neither a link nor a directory: zsh  * existing target is neither a link nor a directory: zsh-5.0.0All operations aborted.

既存ファイルの待避。マニュアルは入らないから一式削除

12345
sudo mv /usr/local/bin/zsh{,.org}sudo mv /usr/local/bin/zsh-5.0.0{,.org}sudo mv /usr/local/share/zsh{,.org}sudo mv /usr/local/lib/zsh{,.org}sudo rm -rf  /usr/local/share/man/man1/zsh*

再度stowコマンドを実行。

12
cd /usr/local/stowsudo stow -v zsh-5.0.0

下記のような形でlinkが貼られる。

123456789101112131415161718192021
LINK: bin/zsh-5.0.0 => ../stow/zsh-5.0.0/bin/zsh-5.0.0LINK: bin/zsh => ../stow/zsh-5.0.0/bin/zshLINK: share/man/man1/zshtcpsys.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshtcpsys.1LINK: share/man/man1/zshparam.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshparam.1LINK: share/man/man1/zshcontrib.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshcontrib.1LINK: share/man/man1/zshoptions.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshoptions.1LINK: share/man/man1/zsh.1 => ../../../stow/zsh-5.0.0/share/man/man1/zsh.1LINK: share/man/man1/zshroadmap.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshroadmap.1LINK: share/man/man1/zshexpn.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshexpn.1LINK: share/man/man1/zshmisc.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshmisc.1LINK: share/man/man1/zshzle.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshzle.1LINK: share/man/man1/zshbuiltins.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshbuiltins.1LINK: share/man/man1/zshcalsys.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshcalsys.1LINK: share/man/man1/zshmodules.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshmodules.1LINK: share/man/man1/zshcompctl.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshcompctl.1LINK: share/man/man1/zshzftpsys.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshzftpsys.1LINK: share/man/man1/zshcompsys.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshcompsys.1LINK: share/man/man1/zshall.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshall.1LINK: share/man/man1/zshcompwid.1 => ../../../stow/zsh-5.0.0/share/man/man1/zshcompwid.1LINK: share/zsh => ../stow/zsh-5.0.0/share/zshLINK: lib/zsh => ../stow/zsh-5.0.0/lib/zsh

ls/usr/local/{bin,lib,share}を確認

12345678910111213
[akira@dev001] $ ll /usr/local/bin/ | grep zshlrwxrwxrwx 1 root root       25 Aug  9 12:42 zsh -> ../stow/zsh-5.0.0/bin/zshlrwxrwxrwx 1 root root       31 Aug  9 12:42 zsh-5.0.0 -> ../stow/zsh-5.0.0/bin/zsh-5.0.0-rwxr-xr-x 1 root root   690064 Jul 23 11:00 zsh-5.0.0.org-rwxr-xr-x 1 root root   687144 Mar 29 13:06 zsh.old[akira@dev001] $ ll /usr/local/lib/ | grep zshlrwxrwxrwx 1 root root   25 Aug  9 12:42 zsh -> ../stow/zsh-5.0.0/lib/zshdrwxr-xr-x 4 root root 4096 Jul 23 11:00 zsh.org[akira@dev001] $ ll /usr/local/share | grep zshlrwxrwxrwx   1 root root   27 Aug  9 12:42 zsh -> ../stow/zsh-5.0.0/share/zshdrwxr-xr-x   5 root root 4096 Jul 23 11:00 zsh.dist

Stowを利用してzshバージョンの切り替え

zsh-4.3.17を導入して、zsh-5.0.0から切り替えをしてみる。

1234567
cd ~/srccurl -Lo zsh-4.3.17.tar.gz http://sourceforge.net/projects/zsh/files/zsh-dev/4.3.17/zsh-4.3.17.tar.gz/downloadtar zxvf zsh-4.3.17.tar.gzcd zsh-4.3.17./configure --prefix=/usr/local/stow/zsh-4.3.17makesudo make install

この状態で/usr/local/stow配下に2つのバージョンがある。

1234
[akira@dev001] $ ll /usr/local/stowtotal 8drwxr-xr-x 5 root root 4096 Aug  9 12:12 zsh-4.3.17drwxr-xr-x 5 root root 4096 Aug  9 11:27 zsh-5.0.0

zsh-5.0.0へのリンクを削除(stow -D)して、zsh-4.3.17にリンクを貼る。

123
cd /usr/local/stow/sudo stow -Dv zsh-5.0.0sudo stow -v zsh-4.3.17

12345678910111213141516171819202122
[akira@dev001] $ sudo stow -v zsh-4.3.17LINK: bin/zsh-4.3.17 => ../stow/zsh-4.3.17/bin/zsh-4.3.17LINK: bin/zsh => ../stow/zsh-4.3.17/bin/zshLINK: share/man/man1/zshtcpsys.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshtcpsys.1LINK: share/man/man1/zshparam.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshparam.1LINK: share/man/man1/zshcontrib.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshcontrib.1LINK: share/man/man1/zshoptions.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshoptions.1LINK: share/man/man1/zsh.1 => ../../../stow/zsh-4.3.17/share/man/man1/zsh.1LINK: share/man/man1/zshroadmap.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshroadmap.1LINK: share/man/man1/zshexpn.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshexpn.1LINK: share/man/man1/zshmisc.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshmisc.1LINK: share/man/man1/zshzle.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshzle.1LINK: share/man/man1/zshbuiltins.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshbuiltins.1LINK: share/man/man1/zshcalsys.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshcalsys.1LINK: share/man/man1/zshmodules.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshmodules.1LINK: share/man/man1/zshcompctl.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshcompctl.1LINK: share/man/man1/zshzftpsys.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshzftpsys.1LINK: share/man/man1/zshcompsys.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshcompsys.1LINK: share/man/man1/zshall.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshall.1LINK: share/man/man1/zshcompwid.1 => ../../../stow/zsh-4.3.17/share/man/man1/zshcompwid.1LINK: share/zsh => ../stow/zsh-4.3.17/share/zshLINK: lib/zsh => ../stow/zsh-4.3.17/lib/zsh

下記でバージョンが切り替わっているか確認。バージョン切り替えが楽。

1234
exec zshzsh --versionzsh 4.3.17 (x86_64-unknown-linux-gnu)

Stow関連の情報は全体的に古いものが多くて、ググっているとオワコン的な雰囲気が漂ってるんですが2012年現在もちゃんとメンテされているので、ソースからビルドするならStowを利用するのが良いかもしれない。

運用としてはwebistranoなどを利用して、

  • ビルドサーバでビルドしたものをデプロイ
  • 各サーバでstowコマンドを実行してバージョン切り替え

という感じになるかなーと考え中。

もう少し突っ込んで検証してみよう。

参考URL

DSAS開発者の部屋:クラッシュダンプからカーネルメッセージを取り出すツール「crashdmesg」を作りました

Linuxカーネルには、カーネルパニック時にkexecを使ってダンプ取得用のカーネル(セカンドカーネル)を起動する仕組みがあります。
このセカンドカーネルは予めリザーブされたメモリ内で起動するため、クラッシュしたカーネルが処理していたメモリの内容はそのまま残っていて、procファイルシステム経由でクラッシュダンプを取得する事ができます。

このDSASブログでも、以前「Linuxでクラッシュダンプを採取(1) ~ kexec + kdump を使ってみる ~」と言うタイトルでクラッシュダンプの取得方法をご紹介しました。

「crashdmesg」は、kexec+kdumpで保存したクラッシュダンプから、カーネルメッセージの内容を取り出すツールです。
デバッガと比べてはるかに軽量なため、セカンドカーネル上で直接/proc/vmcoreからカーネルメッセージを取り出すこともできます。

最近のクラッシュダンプ事情

クラッシュダンプにはサーバ上のメモリの内容がほとんど保存されているため、カーネルメッセージのほか、クラッシュ時に稼働していたプロセスやネットワークの状態など、多くの情報を取得することができます。
カーネルパニックでサーバがダウンした場合、syslog等でのカーネルメッセージの転送は間に合わず、ログが全くない状態で原因究明を行わなければならないことが多く、クラッシュダンプを取得する仕組みは、カーネルに起因するトラブル解析の強い味方です。

しかし、クラッシュダンプを取得する方法にはデメリットもあります。
サーバの搭載メモリのほぼ全てをダンプするため、クラッシュダンプのサイズも搭載メモリに合わせて大きくなり、保存に時間がかかるのです。
例えば弊社では、メモリを72GB搭載して運用しているサーバがあり、この場合では72GB近いダンプファイルをローカルディスクもしくはネットワーク上の他のサーバに転送する必要があります。
転送が終わるまでは、サーバの再起動や調査を行うことができず、復旧が遅れてしまいます。

最小限のダウンタイムで情報集め

そもそも、巨大なダンプファイルを転送する時間がないのであれば、セカンドカーネル上でクラッシュダンプを解析してしまい、結果だけを転送するという方法を思いつきました。
クラッシュダンプを解析するcrashコマンドに、予めカーネルメッセージのダンプや、プロセス、ネットワーク状態等の状況を出力するスクリプトを実行させて、結果のテキストデータだけを転送するという作戦です。
パニックのメッセージやスタックトレースの出力に応じたデバッグはできなくなりますが、カーネルのバグフィックス情報を調べる手がかりぐらいは読み取れるのではないかと考えたのです。

しかし、crashコマンドを実行するには、100MB近いサイズになるデバッグシンボル付きのカーネルが必要になるほか、crashコマンドの実行自体もかなりのメモリを必要とします。
セカンドカーネルは予めリザーブした領域上で動くため、非常時にcrashコマンドを実行するためだけに多量のメモリをリザーブするわけにもいかず断念しました。

crashdmesg

そこで思い切って、取得する情報をカーネルメッセージのバッファ領域だけに絞り、カーネルダンプファイルから直接情報を取得することができないか調べてみました。
すると、いくつかのシンボル情報が取得出来れば、クラッシュダンプからカーネルメッセージのバッファ領域を拾うことができそうだと分かり、「crashdmesg」というツールを作ってみました。

その名のとおり、dmesgコマンドのクラッシュダンプ版をイメージしていて、/proc/vmcoreもしくは引数に指定したダンプファイルからカーネルメッセージをダンプして標準出力に出力します。
軽量なプログラムですので、セカンドカーネル上の僅かなメモリの中でも使うことができます。
しかも、ダンプに必要なシンボル情報をvmcore内から読み取るため、デバッグシンボル付きのカーネルやSystem.mapを用意する必要がありません。

最後に

crashdmesgのソースコードは、githubで公開しています。

https://github.com/hiro-dSn/crashdmesg

crashdmesgの仕組み解説や、kexec+kdump使用のコツなども、追ってこのDSASブログに掲載したいと思います。