[python] 多次元リストにおける複数キーでのソート

pythonで、多次元リストで複数のキーでソートする方法。

list.sort(cmp=lambda x,y: cmp([x[2],x[1]],[y[2],y[1]]))

上記の例では3項目目、2項目目の優先順位でソート項目を設定している。
ちなみにxとyには比較する前後の値(この場合は一次元のリスト)が入っている。
前後の行同士を比較するイメージ。
#マニュアルに書いてないけどcmpの引数はリストも受け付けるのね。
CSVファイルなどを読みこんでソートしたいときに便利

import csv
fd=file("hoge,csv","r")
csvfile=csv.reader(fd)
list=[]
for getline in csvfile:
    list.append(getline)
fd.close()
list.sort(cmp=lambda x,y: cmp([x[2],x[1]],[y[2],y[1]]))

C言語 2重ポインタと関数に渡すときのまとめ

ポインタを関数で使用するときのまとめ。
10年ぶりにC言語を書いて忘れていたので、思い出したのをまとめてみる。
関数をまたぐをわけわからなくなってくる。嵌るポイントはここ。
2重ポインタ ダブルポインタ ポインタのポインタ
値渡し=内容が別のアドレスにコピーされる。呼び出し元とは別ものになる。
関数に値を渡すとき何もしないと値渡しになるから、ポインタを渡すとポインタに格納されているアドレス自身を値渡しすることになる。
なので、渡した関数の中でアドレスを変更すると、値渡しなので関数終了時にアドレスが入った箱が破棄されるので、呼び出し元には反映されない。
関数内でmallocなどでアドレスを変更する場合は2重ポインタで渡せば、2重ポインタのアドレス自身が破棄されても、その実体であるポインタは残るので内容は維持できる。
内容を触るぶんには、アドレスは変更されないので問題なし。ポインタを値渡しすればよし。
●まとめ
・ポインタを関数に渡すとき、
  mallocする場合、二重ポインタで渡す。
  内容のみを触る場合、ポインタをそのまま値渡しすればOK
・3重ポインタなどは要らない
●ソース

#include <stdio.h>
void funcA(unsigned char **);
void funcAA(unsigned char *);
void funcB(unsigned char *);
void funcBB(unsigned char *);
void funcC(unsigned char **);
void funcCC(unsigned char ***);
void funcD(unsigned char **);
void funcDD(unsigned char ***);
void funcE(unsigned char **);
void funcEE(unsigned char **);
int main(){
unsigned char *szA;
unsigned char *szB;
unsigned char *szC;
unsigned char *szD;
unsigned char *szE;
printf(“nポインタ渡し→malloc→値渡し→内容を編集n”);
funcA(&szA);
printf(“A:%sn”,szA);
printf(“n値渡し→malloc→値渡し→内容を編集n”);
funcB(szB);
printf(“B:%sn”,szB);
printf(“nポインタ渡し→malloc→ポインタ渡し→内容を編集n”);
funcC(&szC);
printf(“C:%sn”,szC);
printf(“nポインタ渡し→ポインタ渡し→malloc→内容を編集n”);
funcD(&szD);
printf(“D:%sn”,szD);
printf(“nポインタ渡し→値渡し→malloc→内容を編集n”);
funcE(&szE);
printf(“E:%sn”,szE);
}
void funcA(unsigned char **szDoublePointer){
*szDoublePointer = (unsigned char *)malloc(100);
memset(*szDoublePointer,’’,100);
funcAA(*szDoublePointer);
printf(“AA:%sn”,*szDoublePointer);
}
void funcAA(unsigned char *szPointer){
strcpy(szPointer,”set funcAA”);
}
void funcB(unsigned char *szPointer){
szPointer = (unsigned char *)malloc(100);
memset(szPointer,’’,100);
funcBB(szPointer);
printf(“BB:%sn”,szPointer);
}
void funcBB(unsigned char *szPointer){
strcpy(szPointer,”set funcBB”);
}
void funcC(unsigned char **szDoublePointer){
*szDoublePointer = (unsigned char *)malloc(100);
memset(*szDoublePointer,’’,100);
funcCC(&szDoublePointer);
printf(“CC:%sn”,*szDoublePointer);
}
void funcCC(unsigned char ***szTriplePointer){
strcpy(**szTriplePointer,”set funcCC”);
}
void funcD(unsigned char **szDoublePointer){
funcDD(&szDoublePointer);
printf(“DD:%sn”,*szDoublePointer);
}
void funcDD(unsigned char ***szTriplePointer){
**szTriplePointer = (unsigned char *)malloc(100);
memset(**szTriplePointer,’’,100);
strcpy(**szTriplePointer,”set funcDD”);
}
void funcE(unsigned char **szDoublePointer){
funcEE(szDoublePointer);
printf(“EE:%sn”,*szDoublePointer);
}
void funcEE(unsigned char **szDoublePointer){
/*この場合はダブルポインタの値渡しであるが *
*ダブルポインタ自身を変更してるのではなく、 *
*ダブルポインタの実体(ポインタ)を変更しているので *
*変更内容が呼び出し元に反映される */
*szDoublePointer = (unsigned char *)malloc(100);
memset(*szDoublePointer,’’,100);
strcpy(*szDoublePointer,”set funcEE”);
}

●実行結果

ポインタ渡し→malloc→値渡し→内容を編集
AA:set funcAA
A:set funcAA
値渡し→malloc→値渡し→内容を編集
BB:set funcBB
B:U 藐VS隹x ←ポインタを値渡ししたので、関数内で編集した内容が破棄された
ポインタ渡し→malloc→ポインタ渡し→内容を編集
CC:set funcCC
C:set funcCC
ポインタ渡し→ポインタ渡し→malloc→内容を編集
DD:set funcDD
D:set funcDD
ポインタ渡し→値渡し→malloc→内容を編集
EE:set funcEE
E:set funcEE

[linux]パケットキャプチャ

linuxでパケットキャプチャ
通信してるか確かめるだけなら

# tcpdump -i <NICデバイス名> port <ポート番号> and host <IPアドレス>

通信している内容も確かめたいときは

# tcpdump -Xx -s 4096 -i <NICデバイス名> dst port <ポート番号>? and? src host? <IPアドレス>

後でwiresharkで確かめたいときは(ファイルに保存)

# tcpdump -w <保存するファイル名> -s 4096 -i <NICデバイス名> dst port <ポート番号>? and? src host? <IPアドレス>

ってか最初からwiresharkでやれよ!
CUIフェチなもんで。

[tomcat]tomcatがフリーズしたときの原因究明方法(完全自分用メモ)

tomcatがフリーズしたときの原因究明方法
tomcatのプロセスが生きてるのに、tomcatが反応しないときのフリーズ原因究明方法は、tomcatのプロセス(java)に対してSIGQUITシグナルを送信してJavaスレッドダンプを出力させて、それを見て無限ループもしくはデットロックしている場所を見つける。
Javaスレッドダンプはtomcatからみて標準出力、つまりcatalina.outに出力される。
Javaスレッドダンプには、出力時点で実行中のスレッドの情報(実行状態およびソース上の実行箇所)、Javaのデットロックの情報が出力されている。

# pid=$( ps auwwwwx | egrep “^tomcat.+java ” | grep -v grep | awk ‘{print $2}’ )
# kill -3 ${pid}
# less /usr/local/tomcat/logs/catalina.out

[linux]syslog(messagesなど)にログレベルを表示する

システムログ(syslogで出力するログ)に、ログレベルを出力させる方法。
ログレベル(重大度)でログ監視させたい場合に非常に便利。
rsyslog版はこちら
syslogdの起動オプションに「-SS」を追加する。
RHEL(CentOS)ならこんな感じ。

# vi /etc/sysconfig/syslog
:(省略)
SYSLOGD_OPTIONS=”-m 0 -SS
:(省略)

オプションを追加したらsyslogdを再起動

# service syslog restart

/var/log/messagesにはこんな感じで出力される

Aug 5 01:19:39 <syslog.info> hostname syslogd 1.4.1: restart.
Aug 5 01:19:39 <kern.info> hostname kernel: klogd 1.4.1, log source = /proc/kmsg started.

[solaris] ディスクのミラーリング(ソフトウェアRAID)

solarisでのディスクミラーリング方法

ルート領域と、swap領域、その他の領域で手順が若干異なる
0.metadb作成
metadbの複製のガイドラインは

  • ディスクが1つの場合は3つの複製を作成
  • ディスクが2~4つの場合は2つの複製を作成
  • ディスクが5つ以上の場合は1つの複製を作成

1つのmetadbが論理破損しても、過半数のメタ情報が1つのmetadbに残るようにすることから。(要するに2つのmetadbが残っていれば過半数残っているだろう、という考えから)

# metadb -a -f -c 2 c1t0d0s4 c1t1d0s4

1.ルート領域

# metainit -f d10 1 1 c1t0d0s0
d10:連結/ストライプがセットアップされます
# metainit d20 1 1 c1t1d0s0
d20:連結/ストライプがセットアップされます
# metainit d0 -m d10
d0:ミラーがセットアップされます
# cp -p /etc/vfstab /etc/vfstab.bak
# metaroot d0
# vi /etc/vfstab
#device device mount FS fsck mount mount
#to mount to fsck point type pass at boot options
#
fd /dev/fd fd – – no –
/proc – /proc proc – no –
/dev/dsk/c1t0d0s1 – – swap – no –
/dev/md/dsk/d0 /dev/md/rdsk/d0 / ufs 1 no –
/dev/dsk/c1t0d0s3 /dev/rdsk/clt0d0s3 /usr ufs 1 no –
/dev/dsk/c1t0d0s6 /dev/rdsk/c1t0d0s6 /var ufs 1 no –
/dev/ask/c1t0d0s7 /dev/rdsk/c1t0d0s7 /export/home ufs 2 yes –
/dev/dsk/c1t0d0s5 /dev/rdsk/c1t0d0s5 /opt ufs 2 yes –
swap – /tmp tmpfs – yes –
# lockfs -fa
# sync;sync;sync
# /usr/sbin/shutdown -y -g0 -i6

2.swap領域

# metainit -f d11 1 1 c1t0d0s1
d11:連結/ストライプがセットアップされます
# metainit -f d21 1 1 c1t1d0s1
d21:連結/ストライプがセットアップされます
# metainit d1 -m d11
d1:ミラーがセットアップされます
# metattach d1 d21
d1:サブミラーd21 is attached
# vi /etc/vfstab
#device device mount FS fsck mount mount
#to mount to fsck point type pass at boot options
#
fd /dev/fd fd – – no –
/proc – /proc proc – no –
/dev/md/dsk/d1 – – swap – no –
/dev/md/dsk/d0 /dev/md/rdsk/d0 / ufs 1 no –
/dev/dsk/c1t0d0s3 /dev/rdsk/clt0d0s3 /usr ufs 1 no –
/dev/dsk/c1t0d0s6 /dev/rdsk/c1t0d0s6 /var ufs 1 no –
/dev/ask/c1t0d0s7 /dev/rdsk/c1t0d0s7 /export/home ufs 2 yes –
/dev/dsk/c1t0d0s5 /dev/rdsk/c1t0d0s5 /opt ufs 2 yes –
swap – /tmp tmpfs – yes –

3.その他の領域
長くなるので1領域だけ

# metainit -f d13 1 1 c1t0d0s3
d13:連結/ストライプがセットアップされます
# metainit d23 1 1 c1t1d0s3
d23:連結/ストライプがセットアップされます
# metainit d3 -m d13
d3:ミラーがセットアップされます
# metattach d3 d23
d1:サブミラーd21 is attached
# vi /etc/vfstab
# vi /etc/vfstab
#device device mount FS fsck mount mount
#to mount to fsck point type pass at boot options
#
fd /dev/fd fd – – no –
/proc – /proc proc – no –
/dev/md/dsk/d1 – – swap – no –
/dev/md/dsk/d0 /dev/md/rdsk/d0 / ufs 1 no –
/dev/md/dsk/d3 /dev/md/rdsk/d3 /usr ufs 1 no –
/dev/dsk/c1t0d0s6 /dev/rdsk/c1t0d0s6 /var ufs 1 no –
/dev/ask/c1t0d0s7 /dev/rdsk/c1t0d0s7 /export/home ufs 2 yes –
/dev/dsk/c1t0d0s5 /dev/rdsk/c1t0d0s5 /opt ufs 2 yes –
swap – /tmp tmpfs – yes –

[solaris]システムバックアップリストア(ufsdump/ufsrestore テープ使用 SDS ミラーリング)

Solarisのシステムバックアップおよびにリストア方法

■前提条件

  • 復旧時にインストールCDを用いてCDブートする
  • 復旧時にミラーリングまでは復元しない(シングルディスクで復旧→ミラーリング
  • バックアップイメージはテープに保存
  • ファイルシステムはUFS
  • フルバックアップのみ

■ バックアップ
ローカルディスクのマウントしている全ファイルシステム(スライス)をテープにバックアップ。metadbなどはバックアップしない。

# mt -f /dev/rmt/0 rewind
# ufsdump 0uf /dev/rmt/0n /dev/md/rdsk/d10
# ufsdump 0uf /dev/rmt/0n /dev/md/rdsk/d40
# ufsdump 0uf /dev/rmt/0n /dev/md/rdsk/d60
# ufsdump 0uf /dev/rmt/0n /dev/md/rdsk/d70
# ufsdump 0uf /dev/rmt/0n /dev/md/rdsk/d80

■リストア
1.インストールCDからシングルユーザモードでブートする
起動途中(POSTやメモリ初期化、ハードウェア検索が終わったあと、boot ~ optionの表示があった後)でSTOP+A(TeraTermからのシリアル接続の場合はAlt+B)を押して、OKプロンプトに移行し、以下を入力

{1} ok boot cdrom -sr

2.ディスクスライスの設定
シングルユーザモードで起動したら、まず最初にやるのはディスクスライスの設定(スライスっていうのはsolarisぐらい??)。
ミラーリングする場合は2つのディスクでシリンダーの開始位置終了位置をピッタリ合わせる必要あり。

# format
format> type
AVAILABLE DISK SELECTIONS:
0. c1t0d0 (SUN72G cy1 14087 alt 2 hd 24 see 424)
/pci@1c,600000/scsi@2/sd@0,0
1. c1t1d0 (SUN72G cyl 14087 alt 2 hd 24 see 424)
/pci@lc,600000/scsi&/sd@1,0
specify disk (enter its number) : 0
selecting c1t0d0
:(省略)
19. SUN72G
20. Other
specify disk type (enter its nubber) [19]:
selecting c1t0d0
[disk formatted]
format> partition
partion> 0
Enter partion id tag [root]:
Enter partion permission flag[vm] :
Enter nev starting cyl [0]
Enter partion size[] ←ここは「1234e」とシリンダーの終了位置を
入力したほうが両ディスクでサイズをそろえやすい
:(省略)
partition> print
current partition table (original) :
Total disk cylinders available: 14087+2 (reserved cylinders)
Part Tag Flag Cylinders Size Blocks
0 root wm 0 – 2060 10. 00GB (2061/0/0) 20972736
1 swap wu 2061 – 3091 5. 00GB (1031/0/0) 10491456
2 backup vm 0 – 14086 68. 35GB (14087/0/0) 143349312
3 usr wm 3092 – 5152 10. 00GB (2061/0/0) 20972736
4 unassigned wm 5153 – 5157 24. 84MB (5/0/0) 50880
5 unassigned wm 5158 – 7218 10. 00GB (2061/0/0) 20972736
6 var vm 7219 – 9279 10. 00GB (2061/0/0) 20972736
7 home vm 9280 – 14086 23, 32GB (4807/0/0) 48916032

3.ファイルシステム作成(フォーマット)
マウントして使用するスライスにファイルシステムを作成してフォーマット。
+metadb領域も。ミラーリングする場合はもう片方のmetadb領域もファイルシステム作成する

# newfs /dev/rdsk/c1t0d0s0
# newfs /dev/rdsk/c1t0d0s3
# newfs /dev/rdsk/c1t0d0s4
# newfs /dev/rdsk/c1t1d0s4
# newfs /dev/rdsk/c1t0d0s5
# newfs /dev/rdsk/c1t0d0s6

4.テープの内容確認(わかっている場合はやらなくてもよい)
テープデバイスにnをつけてufsrestoreを連続実行すれば、いちいちテープに対する操作をしなくてもよい

# mt -f /dev/rmt/o rewind
#
# ufsrestore if /dev/rmt/0n
ufsrestore > ls
.:
2 *./ 116 kernel/ 128 sbin/
2 *‥/ 125 1ib 131 tmp/
1160 . sh_history 3487 logfile 3486 dump.ksh
9 bin 3 lost+found/ 3485 dump.log
6773 cdrom/ 126 mnt/ 4 usr/
10 dev/ 6771 net/ 5 var/
12 devices/ 3488 nohup.out 7767 vol/
14 etc/ 8 opt/ 6772 xfn/
6 export/ 476 platform/
1193 home/ 127 proc/
ufsrestore > what
Dump date: Mon Dec 29 17:13:25 2009
Dumped from: the epoch
Level 0 dump of / on test:/dev/md/dsk/d10
Label: none
ufsrestore > quit
#
# ufsrestore if /dev/rmt/0n
ufsrestore > ls
:(省略・繰り返し)
# mt -f /dev/rmt/0 rewind

5.ファイルシステムリストア
/mntにファイルシステムをマウントしてリストアする。
ufsrestoreするときのテープデバイスの指定にnを忘れぬこと(どこまでやったかわからなくなる)。
またアンマウントする前にsyncすること。

# mount /dev/dsk/c1t0d0s0 /mnt
# cd /mnt
# ufsrestore rf /dev/rmt/0n
# rm restoresymtable
# sync;sync;sync
# cd
# umount /mnt
# fsck /dev/dsk/c1t0d0s0
:(省略・繰り返し)

6.マウントテーブル変更(ミラーリング環境のみ)
ルートファイルシステムをマウントして、/etc/vfstabの内容を変更する。理由はマウントするデバイスファイルがミラーリング側のデバイスファイルになっているから(今回はミラーリングせずにリストアする(後にミラーリングしなおし))

/dev/md/dsk/d10 → /dev/dsk/c1t0d0s0
/dev/md/rdsk/d10 → /dev/rdsk/c1t0d0s0

# mount /dev/dsk/c1t0d0s0 /mnt
# cp -p /mnt/etc/vfstab /mnt/etc/vfstab.bak
# export TERM=vt100 ←シリアル接続でteraterm使っているときなど
# vi /mnt/etc/vfstab
:(省略)
/dev/dsk/c1t0d0s0 /dev/rdsk/c1t0d0s0 / ufs 1 no –
:(省略)

7.ミラーリング(ソフトウェアRAID)解除
ミラーリングを定義しているファイルの内容を消して、ミラーリングのサービスを起動しないようにする。
ミラーリングを定義しているファイルは2つ

  • /etc/lvm/md.cf
  • /etc/lvm/mddb.cf

/etc/lvm/md.cfはヘッダーの2行だけ残して、その他の内容を消す

# cp -p /mnt/etc/lvm/md.cf /mnt/etc/lvm/md.cf.bak
# head -n 2 /mnt/etc/lvm/md.cf.bak > /mnt/etc/lvm/md.cf

/etc/lvm/mddb.cf は「* Begin MDD root info (do not edit)」から「* End MDD root info (do not edit)」までの行の内容を消す

# cp -p /mnt/etc/lvm/mddb.cf /mnt/etc/lvm/mddb.cf.bak
# grep -n “Begin MDD root info” /mnt/etc/lvm/mddb.cf
79:* Begin MDD root info (do not edit)
# head -n 78 /mnt/etc/lvm/mddb.cf.bak > /mnt/etc/lvm/mddb.cf

8.metadbの内容消去
上記3で既にしているが、念のため・・・

# newfs /dev/rdsk/c1t0d0s4
# newfs /dev/rdsk/c1t1d0s4

9.ブートローダインストール
最後の仕上げ。
ブートローダをインストールする。これを忘れると起動しないので必ず実行すること。

# installboot /usr/platform/`uname -i`/lib/fs/ufs/bootblk /dev/rdsk/c1t0d0s0
# sync;sync;sync

10.後片付け

# umount /mnt
# mt -f /dev/rmt/0 offline

11.OS停止
リブートせずにいったんokプロンプトに戻る

shutdown -y -g0 -i0

OSが停止したらCD-ROMを取り出す
12.OS起動
念のため-rオプションでデバイスファイルを再作成してOSを起動する

{1} ok boot -r

13.metadb情報削除
OSが起動したら、中途半端に残っているmetadbの情報を削除する

# metadb -i
フラグ 最初のブロック ブロック数
F M p 16 未知 /dev/dsk/c1t1d0s4
a p 1 8208 8192 /dev/dsk/c1t1d0s4
# metadb -f -d /dev/rdsk/c1t1d0s4

以上。
ミラーリング構築に関しては別記事で。
# metadbの中に、meta情報が過半数以上ないと復帰できないんやったら意味ないやん
# 2本のうち1本のディスクが死ぬ→過半数消滅⇒復帰できるかは割り振りの運次第

[solaris]CD/DVDをマウントできないときの対処法

solarisでCD/DVDディスクをマウントできないときのマウントする方法

solaris 9 あたりから、CD/DVDのマウントが簡単にできない。(CUIは特に)
原因はvolmgtというディスクを管理する?デーモンがお邪魔をしているから。
何も対処しないでマウント使用とするとこうなる。

# mount -F hsfs -o ro /dev/dsk/c0t0d0s0 /cdrom
mount: /dev/dsk/c0t0d0s0はすでにマウントされているか、 /cdromが使用中であるか、
または許容マウントポイント数を超えています。

マウントするためには、このvolmgtというデーモンを先に停止すること。

# /etc/init.d/volmgt stop
# mount -F hsfs -o ro /dev/dsk/c0t0d0s0 /cdrom
#

これで無事にCD/DVDをマウントできた
ちなみに、CD/DVDドライブのデバイスファイル名を調べるには以下のコマンドを実行する。

# iostat -En
 :(省略)
c0t0d0 Soft Errors: 11 Hard Errors: 1 Transport Errors: 0
Vendor: TEAC Product: DV-28E-N Revision: 1.6A Serial No:
Size: 9. 30GB <9302294528 bytes>

※太字個所がデバイスファイル名

CDブートLinuxを使った、ディスク内容を完全消去する方法

CDブートLinuxを使った、ディスク内容を完全消去する方法。
CDブートできるものであればKNOPIXでも各種Linuxのレスキューモードでも何でも良い。
以下のコマンドを実行。

# dd if=/dev/urandom of=/dev/hda bs=104857600
# dd if=/dev/urandom of=/dev/hda bs=104857600
# dd if=/dev/zero of=/dev/hda

bsオプションは一度に書き込むバイト数。これを指定しないとデフォルトのものすごく小さな値が使われるので、ちまちまディスクを書き込むことになり、ものすごく時間がかかる。
/dev/urandomはランダムな値を出力する特殊なファイル。これを使ってディスク全体を2回ほど上書きすれば、ぐちゃぐちゃになるので復元不可能になる。
/dev/zeroは、まっさらな値を出力する特殊なファイル。これを使ってディスク全体を書き込むと、何にも記録されていない状態になる。
上では分けて書いたが、「;」を使って一行に一気に書いて実行すれば、一回一回の上書きごとにコマンドを打つ必要も待つ必要もない

# dd if=/dev/urandom of=/dev/hda bs=104857600;dd if=/dev/urandom of=/dev/hda bs=104857600;dd if=/dev/zero of=/dev/hda

[linux]マルチパスSANブート+ボリュームコピー環境でのリストア方法

Linux(RHEL)+マルチパスSANブート+ディスク装置のボリュームコピー環境でのシステムリストア方法。
最近では、ディスク装置の機能として持っている、論理ボリュームを丸ごとコピーする機能を利用して、システムバックアップを取得するのが、お手軽バックアップとして流行っている模様。
これを利用すると、コピー元のディスクがつぶれた場合、コピー先のディスクをホストに見せるようにするだけで(プレゼントやらマッピングやらマスキングやら・・・)リストアできるように見えるが、LInux+マルチパスSANブート環境だと簡単にはいかない。
その解決方法を以下に示す。
※ディスク装置はHP MSAを想定
※このバックアップ方法は、業務を停止することなくバックアップを取得できるメリットがある、とメーカーは言うが、OSが何しようとが関係なしに、ディスク装置側で勝手にバックアップをとってしまうため、不整合なファイルシステムの状態をとってしまうかもしれないリスクがある。(例えば、ファイル書き込み中とか・・・)


1.コピー先のディスクを、ホストに見せる(MSAの場合はマッピング)。これは当然
2.ホストをブートしてみる・・・・
3.するとinitrd処理中にエラーになり、やがてVGの重複が発生し、レスキューのためのパスワード入力プロンプトが表示されて停止する
(エラーになる原因は、ボリュームコピーによりマルチパスを構成するためのwwidが実際の物と異なっているので、マルチパスが構成できず全パスが個別の重複したディスクとして見えてしまう。マルチパスはwwidをヒントに同一ディスクの複数パスを探し出す。)
# ここで、あきらめる人が多いはず・・・
4.rootのパスワードを入力する
5./bootであるデバイスをマウントする(但し/bootのファイルシステムがパーティションの上に直接乗っているときのみ。LVM不可!)
普段/bootが/dev/mapper/mpath0p1なら、/dev/sda1。(sdb1でもsdc1でもsdd1でも可。実体は同じ)

# mount /dev/sda1 /boot

6.initrdを展開する
 initrdの中のファイルをいくつか編集するので、イメージを展開する。

# cd /boot
# cp -p initrd-xxxxx.img initrd-xxxxx.img.bk
# mkdir tmp
# cd tmp
# zcat initrd-xxxxx.img | cpio -i -o

7.論理ボリュームのSCSIシリアル番号(wwid)を調べる
/dev/disk/by-id/ディレクトリにあるシンボリックリンク名の頭「scsi-」を削ったものが論理ボリュームのSCSIシリアル番号。

# ls /dev/disk/by-id/
scsi-1111222233334444aaaabbbbccccdddd
scsi-1111222233334444aaaabbbbccccdddd-part1
scsi-1111222233334444aaaabbbbccccdddd-part2

上の赤太字がSCSIシリアル番号。
8. initスクリプト中のmultipathコマンドで指定してある論理ボリュームのSCSIシリアル番号(wwid)をコピー先ディスクの番号に書き換える(下、赤斜体文字箇所)。

# vi init
:(省略)
/bin/multipath -v 0 1111222233334444aaaabbbbccccdddd
:(省略)

9.etc/multipath.conf中の信頼する論理ボリュームのSCSIシリアル番号(wwid)を新しい番号に書き換える(下、赤斜体文字箇所)。

vi etc/multipath.conf
blacklist_exceptions {
wwid “1111222233334444aaaabbbbccccdddd
}

10.var/lib/multipath/bindingsファイル中のデバイス名エイリアスに紐づける論理ボリュームのSCSIシリアル番号(wwid)をコピー先の番号に書き換える(下、赤斜体文字箇所)。

# vi var/lib/multipath/bindings
mpath0 1111222233334444aaaabbbbccccdddd

 (このファイルで、wwid:1111222233334444aaaabbbbccccddddのディスクはmpath0を使用すると定義している)
11.initrd再作成
 次回以降の起動で使用できるように、編集したinitrdを再作成(イメージ化)する。

# find . | cpio –quiet -o -c | gzip -c > ../initrd-xxxxx.img

12.再起動

# exit

以上で、めでたく起動できる。