RAIDの再構築に失敗した件についてRAIDアレイの再作成を行った

注意事項、何をやっているのか、よくわからない場合はマネしないように。

/dev/sdbからsdiまでの8台にてRAIDアレイを再作成することになった。

まず、先頭の1GB程度をバックアップする。

dd if=/dev/sdb of=sdb.img bs=1G count=1
dd if=/dev/sdc of=sdc.img bs=1G count=1
dd if=/dev/sdd of=sdd.img bs=1G count=1
dd if=/dev/sde of=sde.img bs=1G count=1
dd if=/dev/sdf of=sdf.img bs=1G count=1
dd if=/dev/sdg of=sdg.img bs=1G count=1
dd if=/dev/sdh of=sdh.img bs=1G count=1
dd if=/dev/sdi of=sdi.img bs=1G count=1

1GBも必要はないのだが、一応やっておく。
1GBの根拠は前回書かなかったが、RAID6の再作成をしたときにデータのオフセットが262144セクタ=134,217,728バイトであることが分かっており、データの先頭部分を含めてバックアップをしたかったため。

ここから先の作業はRAID6の再構築を行ったときのようにloopデバイスを作成して実験したのち、物理デバイスで作業を行っている。

superblockが消えた件について、うっすら、GPT関係が悪影響を及ぼしているのではないのかという懸念があるので、削除をしておく。

# sgdisk -Z /dev/sdb

この作業を行った時点でMBRとGPTが削除される。mdadmのsuperblockが0x00001000(4096バイト地点)に書き込まれていた場合、そのsuperblockも削除されることを確認した。
また、UUIDも削除されてしまうことに後で気づき、焦った。hexdumpでバイナリをバックアップと比較することでドライブの対応をとることができた。

その後、デバイスの順番をRAID構築時の通りに並べて、再作成を行った。

# mdadm -C -l6 -n8 --data-offset=262144s /dev/md0 /dev/sdc /dev/sdc...

mdadmのsuperblockはすべてのドライブから削除されていたので、確認は何も表示されることなく作成がされた。

これにて、再度、ソフトウェアRAIDを利用することができるようになった。

この後superblockがどうなるかわからない怖さがあるので、先頭のバックアップを行った。

dd if=/dev/sdb of=sdb.img bs=1M count=1
dd if=/dev/sdc of=sdc.img bs=1M count=1
dd if=/dev/sdd of=sdd.img bs=1M count=1
dd if=/dev/sde of=sde.img bs=1M count=1
dd if=/dev/sdf of=sdf.img bs=1M count=1
dd if=/dev/sdg of=sdg.img bs=1M count=1
dd if=/dev/sdh of=sdh.img bs=1M count=1
dd if=/dev/sdi of=sdi.img bs=1M count=1

なお、これらのディスクの0x00001000(4096バイト)時点にてmdadmのsuperblockが書き込まれていることは確認している。

新しいマザーボードへ移設したRAIDの再構築に失敗した件について

前回のRAID6復旧時に「よりよい筐体を」「eSATAでは速度に難がある」「これを機にCPUも含めて刷新を」という雰囲気に至ったので、毎年末に行っているメンテナンス作業を早めて11月時点で、RAIDを構成しているHDDを新しい筐体やマザーボードへ乗せ換えることとした。

RAIDの再構成ができない

新しい筐体・マザーボードに乗せ換えて、新しいSSDUbuntu 16.04をインストール。その後、HDDを移設して接続して起動して、mdadmで再構築を行った。ところが認識されない。mdadm -A(--assemble)を行ってもsuperblockが見つからないとのこと。

そこで、mdadmからraidのsuperblockの情報がどうなっているのか、見に行く。

# mdadm -E /dev/sdb
/dev/sdb:
   MBR Magic : aa55
Partition[0] :   4294967295 sectors at            1 (type ee)

見えない。存在しない。

通常、mdadmのメタバージョン1.2では、オフセット8セクタの場所にsuperblockの情報が書き込まれていることが分かっている。

例えば、前回の記事でRAID6の復旧に利用したメタ情報から抜き出すと、以下のように見える。

# mdadm -E /dev/sde | grep Super
   Super Offset : 8 sectors

ディスクは1セクタ=512バイトであるので、8セクタ=4096バイトのオフセットのバイナリを見ることでsuperblockの存在を確認できる。

sdbのsuperblockを確認する。

# hexdump -C -n 5000 /dev/sdb
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 ff  |................|
000001c0  ff ff ee ff ff ff 01 00  00 00 ff ff ff ff 00 00  |................|
000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200  45 46 49 20 50 41 52 54  00 00 01 00 5c 00 00 00  |EFI PART....\...|
00000210  1e e0 4b 5f 00 00 00 00  01 00 00 00 00 00 00 00  |..K_............|
00000220  af a3 50 5d 01 00 00 00  22 00 00 00 00 00 00 00  |..P]....".......|
00000230  8e a3 50 5d 01 00 00 00  63 20 c9 10 f5 f3 41 0f  |..P]....c ....A.|
00000240  8c a0 ac b9 35 55 87 e6  02 00 00 00 00 00 00 00  |....5U..........|
00000250  80 00 00 00 80 00 00 00  b9 f0 6c 32 00 00 00 00  |..........l2....|
00000260  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400  c3 8c 89 6a d2 1d b2 11  99 a6 08 00 20 73 66 31  |...j........ sf1|
00000410  5a da 25 4e 9f f5 41 3c  8c 55 b7 d8 2a a8 5a 32  |Z.%N..A<.U..*.Z2|
00000420  00 08 00 00 00 00 00 00  ff 5f 50 5d 01 00 00 00  |........._P]....|
00000430  00 00 00 00 00 00 00 00  7a 00 66 00 73 00 00 00  |........z.f.s...|
00000440  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000800  3b 5a 94 6a d2 1d b2 11  99 a6 08 00 20 73 66 31  |;Z.j........ sf1|
00000810  ef ab 9b c3 cf 46 48 fa  88 af 3f c5 e6 0c 87 60  |.....FH...?....`|
00000820  00 60 50 5d 01 00 00 00  ff 9f 50 5d 01 00 00 00  |.`P]......P]....|
00000830  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001388

0x00000830から0x00001388まで飛ばされていて0x00001000(4096)の場所には何も書き込まれていないことになっている。
ちなみに0x000001fe(510バイト)にMBRのブートシグニチャである0xaa55(リトルエンディアン)が見える(マスターブートレコード)。その後に"EFIPART"の文字列が続くが、これはGPT(GUID PARTITION TABLE)のシグニチャである。

ともかく、このことからsuperblockが存在しないように見える。悲しい。

ちなみに1台だけsuperblockの情報が見えるHDDが存在した。

# hexdump -C -n 5000 /dev/sde
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000  fc 4e 2b a9 01 00 00 00  01 00 00 00 00 00 00 00  |.N+.............|
00001010  fb 80 6f e4 de 7f cc e6  ae 17 5e bb 2e dd c9 b1  |..o.......^.....|
00001020  6d 78 31 33 30 73 32 3a  33 00 00 00 00 00 00 00  |mx130s2:3.......|
00001030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001040  a9 ce 1d 58 00 00 00 00  06 00 00 00 02 00 00 00  |...X............|
00001050  00 a0 4c 5d 01 00 00 00  00 04 00 00 08 00 00 00  |..L]............|
00001060  08 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001080  00 00 04 00 00 00 00 00  b0 a3 4c 5d 01 00 00 00  |..........L]....|
00001090  08 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000010a0  04 00 00 00 00 00 00 00  46 18 70 eb 85 31 f5 41  |........F.p..1.A|
000010b0  10 01 d0 3d de 89 c8 31  00 00 08 00 48 00 00 00  |...=...1....H...|
000010c0  9a e0 22 58 00 00 00 00  e8 63 00 00 00 00 00 00  |.."X.....c......|
000010d0  ff ff ff ff ff ff ff ff  dd 60 aa 56 80 00 00 00  |.........`.V....|
000010e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001100  00 00 01 00 02 00 03 00  04 00 05 00 fe ff fe ff  |................|
00001110  07 00 06 00 fe ff fe ff  fe ff fe ff fe ff fe ff  |................|
00001120  fe ff fe ff fe ff fe ff  fe ff fe ff fe ff fe ff  |................|
*
00001200  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001388

RAID superblock formatsを参考にsuperblockの形式を調べると、0x00001000(4096バイト)の場所に0xa92b4efc(little-endian)がMagic Numberとして書き込まれるはず。

00001000  fc 4e 2b a9 01 00 00 00  01 00 00 00 00 00 00 00  |.N+.............|

を見ると、確かにリトルエンディアンでMagic Numberが書き込まれている。

埒が明かないので、HDDを何台か以前の環境に戻してみたが、mdadm -Eしてもhexdumpしても、結果は相変わらず。superblockのデータは環境が変わったから見えなくなった、という線を期待していたのだが、そうではなく、本当に消えてしまったようだ。

まとめ

RAIDが再構成できなかったことについて、いくつかの可能性が考えている。

  • 書き込んだと思っていたsuperblockが書き込まれていなかった
  • superblockの書き込みには成功したがHDDの移動時に削除された(してしまった)

とはいえ、これらのHDDはインストール作業が終わってから移動したので、インストーラーは絡んでいない。MBRやGPTのパーティションテーブルを変更した記憶もない。mdadm --zero-superblockをこれらのHDDに行った記憶もない。疑問だらけだ。

前回の教訓から、大事なデータはバックアップを取っており大事には至っていない。とはいえ、こうした現象が起こるということを踏まえて

  • RAIDに参加しているHDDの先頭1MB程度はバックアップを取っておいたほうが良いのかもしれない
  • もしくはディスク全体をmdadmでRAIDにするのではなく、パーティションを切ってからそのパーティションRAIDを構築するほうがよかったのではないか

とうっすら思っているが、これで大丈夫だという確証はない。

ともかく、RAIDを再構成するためには、HDDの順番を確認してmdadm -C(--create)で再作成するしかないだろうことが分かった。

LinuxのRAID6復旧について

RAIDはバックアップではない。
ということを雑談で話しながら自分はバックアップ領域を作っていなかった。

そして痛い目に会い、再度、肝に銘じる。
繰り返す。RAIDはバックアップではない。

何があったのか

趣味の自鯖をRAID6を8台で構成していた。
ある日突然、RAID領域にアクセスできなくなったので調べてみると、8台中、4台が不調。
/proc/mdstatを見ると

[_UUUU___]

こりゃあかん。

ポートマルチプライヤできるeSATAインターフェースの2口から、裸族の集合住宅5BayというHDDが5台入ることができる製品を2台使って、4台・4台で分けている。どうやら、この1つに所属していたHDDがRAIDから外れているようだ。辛い。

状況を確認する

まず、一通りのSMART情報を確認する。特にSMART上では8台とも問題はないようだ。

SMART情報に問題がないようなら、RAIDを再結成してもよさそうなので

# mdadm -A --scan

などを実行する。が、うまくいかない。うち3台にてpossibly out of dateというエラーが出る。たぶん、時代遅れっすか。

雑に[a-z]指定でRAIDでスーパーブロックの中にある情報を読みに行く。これによってsdaからsdzまで読む。

# mdadm -E /dev/sd[a-z] | grep Events
         Events : 1797391
         Events : 1797391
         Events : 1797391
         Events : 1797391
         Events : 1797391
         Events : 1797381
         Events : 1548613
         Events : 1797381

なるほど。sdbからsdiまでの8台のうち、sdbからsdfまでは同期がとれているが、sdg,sdh,sdiが同期がとれていない。
というか、sdh。お前いつから外れていたんだ...。

幸いなことに、sdg,sdhはそのほかのHDDとそれほどEventsが離れていない。
RAID6は最低限、n-2台が生きていればいい。8台のうち6台が近いイベント数である。
これが意味するところは、復旧できる可能性が高いということである。

ところでsdhに関しては、以下の結果を見ると、Oh...20日以上前に外れてますやん...ということが分かり、「縮退したらメール出すようにしよう」という決意を新たにした。

# mdadm -E /dev/sd[a-z] | grep Update
    Update Time : Wed Nov  2 09:00:20 2016
    Update Time : Wed Nov  2 09:00:20 2016
    Update Time : Wed Nov  2 09:00:20 2016
    Update Time : Wed Nov  2 09:00:20 2016
    Update Time : Tue Nov  1 21:24:57 2016
    Update Time : Tue Nov  1 21:24:57 2016
    Update Time : Mon Oct 10 07:47:37 2016
    Update Time : Tue Nov  1 21:24:57 2016

ちなみにArray Stateを並べてみると

# mdadm -E /dev/sd[a-z] | grep "Array State"
   Array State : .AAAA... ('A' == active, '.' == missing, 'R' == replacing)
   Array State : .AAAA... ('A' == active, '.' == missing, 'R' == replacing)
   Array State : .AAAA... ('A' == active, '.' == missing, 'R' == replacing)
   Array State : .AAAA... ('A' == active, '.' == missing, 'R' == replacing)
   Array State : AAAAAA.A ('A' == active, '.' == missing, 'R' == replacing)
   Array State : AAAAAA.A ('A' == active, '.' == missing, 'R' == replacing)
   Array State : AAAAAAAA ('A' == active, '.' == missing, 'R' == replacing)
   Array State : AAAAAA.A ('A' == active, '.' == missing, 'R' == replacing)

となっていた。まずsdhが外れて、その後、sdhと同じ側の3台が外れたようだ。

状況を整理する。
RAID6で組んでいた8台のうち、4台が外れた状態になっている。
中身のデータは8台中、5台は完璧に、2台はギリギリセーフ、1台はアウト。
ギリギリセーフのうちの1台を完璧5台と組み合わせれば、多くのデータは救えるだろうと考えられる。

RAIDスーパーブロックの再作成

前章でmdadm -A(--assemble) --forceを実行してダメだった。
これはもう再作成(mdadm -C, --create)しかない。

とはいえ、再作成は怖いので、HDDの先頭部分をファイルに落として、ループデバイスから再作成の実験を行う。

# dd if=/dev/sdb of=/mnt/sdb.img bs=1G count=1

上記のようなコマンドで先頭1GBずつイメージファイルに落とす。これを8台分。
先頭1GBなのでファイルは取り出さず、アレイが再構成できるかどうかまでを検証する。
1GBもいらないが、アレイが修復できてファイルも取り出せたらラッキー感覚で1GB。

実験を何回かする予定なので、tmpに一度コピーしてループデバイスを作成する。

cp /mnt/sd* /tmp
losetup /dev/loop0 /tmp/sdb.img
losetup /dev/loop1 /tmp/sdc.img
losetup /dev/loop2 /tmp/sdd.img
losetup /dev/loop3 /tmp/sde.img
losetup /dev/loop4 /tmp/sdg.img
losetup /dev/loop5 /tmp/sdh.img
losetup /dev/loop6 /tmp/sdi.img
losetup /dev/loop7 /tmp/sdj.img

これをシェルスクリプトに書いておき、何度も実験。

これによって、loop[0-7]に8台分のデバイスができている。

# mdadm -E /dev/loop0

したら、RAIDのスーパーブロックの情報がそのまま出てくるはず。

このループデバイスを使ってRAID構成の再作成を行う。

RAID構成の再作成を行うには、デバイスの順番が重要であり、これを間違うとデータが壊れる。
あらかじめ、以下のコマンドを実行して、何番のデバイスだったのかを確認する。

# mdadm -E /dev/loop[0-7] | grep "Role"
   Device Role : Active device 2
   Device Role : Active device 3
   Device Role : Active device 1
   Device Role : Active device 4
   Device Role : Active device 0
   Device Role : Active device 5
   Device Role : Active device 6
   Device Role : Active device 7

この情報によると、4,2,0,1,3,5,6,7の順番に/dev/loopを構成しなくてはならないことが分かる。

この8台のうち6台を使って復旧する予定なので、実際は4,2,0,1,3,5までを利用することとする。この順番通りに記述する。
2台足りないが、これはmissingを記述すれば縮退運転となる。(missingの場所は重要で例えばloop4をmissingとする場合はloop4の場所にてmissingを書く必要がある。)

# mdadm -C -l6 -n8 /dev/md0 /dev/loop4 /dev/loop2 /dev/loop0 /dev/loop1 /dev/loop3 /dev/loop5 missing missing
mdadm: /dev/loop4 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/loop4 but will be lost or
       meaningless after creating array
mdadm: /dev/loop2 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/loop2 but will be lost or
       meaningless after creating array
mdadm: /dev/loop0 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/loop0 but will be lost or
       meaningless after creating array
mdadm: /dev/loop1 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/loop1 but will be lost or
       meaningless after creating array
mdadm: /dev/loop3 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: /dev/loop5 appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/loop5 but will be lost or
       meaningless after creating array
Continue creating array? yes
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

# mount /dev/md0 /mnt2
mount: unknown filesystem type 'zfs_member'

このmdadm -Cではメタデータがあるが上書きしてもよろしいかと聞かれるのでyesとする。
成功したら、mountしてみる。

が、うまくいかない。

どうもファイルシステムzfs_memberと認識されてしまう。そりゃ確かにzfsは使ったことがあるが...もともとのファイルシステムはxfsを使っていたことがfstabから分かっている。

どうしたもんかなと、作成されたアレイのスーパーブロックを過去のスーパーブロックと見比べていると気になる箇所が出てきた。
当初のバックアップ時のメタデータでは、以下のように

# mdadm -E /dev/loop[0-7] | grep "Data Offset"
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors

データオフセットは262144セクタなのだが、新しく構成したアレイでは、

t# mdadm -E /dev/loop[0-7] | grep "Data Offset"
    Data Offset : 2048 sectors
    Data Offset : 2048 sectors
    Data Offset : 2048 sectors
    Data Offset : 2048 sectors
    Data Offset : 2048 sectors
    Data Offset : 2048 sectors
    Data Offset : 262144 sectors
    Data Offset : 262144 sectors

という風に2048セクタになっている。

あー、なるほど。もともとは262144セクタからデータが始まっていたんだが、新しく構成したアレイでは2048セクタから始まっている。
そのため、もともと何も書いていない領域を読みに行き、ファイルシステムを誤認識してzfs_memberと表示されてしまっている、と。

これはmdadmのバージョンによって異なるのか?良くわからない。よくわからないが、mdadm -C時に--data-offsetを指定できるようだ。

# mdadm -C -l6 -n8 --data-offset=262144s /dev/md0 /dev/loop4 /dev/loop2 /dev/loop0 /dev/loop1 /dev/loop3 /dev/loop5 missing missing

改めて、data-offsetを指定しての作成。うまくいったので、マウント。

# mount /dev/md0 /mnt2
mount: wrong fs type, bad option, bad superblock on /dev/md0,
       missing codepage or helper program, or other error

       In some cases useful info is found in syslog - try
       dmesg | tail or so.

Oh、失敗。

# dmesg | tail
[126834.393569]  disk 0, o:1, dev:loop4
[126834.393571]  disk 1, o:1, dev:loop2
[126834.393572]  disk 2, o:1, dev:loop0
[126834.393574]  disk 3, o:1, dev:loop1
[126834.393576]  disk 4, o:1, dev:loop3
[126834.393577]  disk 5, o:1, dev:loop5
[126834.393591] md/raid456: discard support disabled due to uncertainty.
[126834.393593] Set raid456.devices_handle_discard_safely=Y to override.
[126834.393632] md0: detected capacity change from 0 to 5637144576
[126842.935838] XFS (md0): Filesystem has duplicate UUID d3003f02-563b-44fb-a15e-9b41bd6f6f82 - can't mount

dmesgによると、XFSを一応理解してくれている様子。良かった。補足するとmdadm -Cするときに順番を間違えると、XFSとすら認識されなかった。こういった間違いを犯すのでddしたイメージ上で作業すると非常に気が楽。

# xfs_repair /dev/md0
Phase 1 - find and verify superblock...
error reading superblock 1 -- seek to offset 187528904704 failed
couldn't verify primary superblock - attempted to perform I/O beyond EOF !!!

attempting to find secondary superblock...
......................................................................................

xfs_repairしてみるが、ファイルシステムのスーパーブロックが見つからない、と来たか。

ここで、ファイルシステムの復元までの道筋がついた。
本来であれば、HDDのすべてのバックアップを取って、ループデバイス上でxfsをマウントしたいところだが、そうもいかない。

ということでギャンブルの時間。自己責任。ちなみに、このときはsdfに別のHDDが割り込んでしまったので、sdfとsdgがズレてsdgとsdhになっている。

# mdadm -C -l6 -n8 --data-offset=262144s /dev/md3 /dev/sdg /dev/sdd /dev/sdb /dev/sdc /dev/sde /dev/sdh missing missing
mdadm: /dev/sdg appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/sdg but will be lost or
       meaningless after creating array
mdadm: /dev/sdd appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/sdd but will be lost or
       meaningless after creating array
mdadm: /dev/sdb appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/sdb but will be lost or
       meaningless after creating array
mdadm: /dev/sdc appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/sdc but will be lost or
       meaningless after creating array
mdadm: /dev/sde appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: /dev/sdh appears to be part of a raid array:
       level=raid6 devices=8 ctime=Sat Nov  1 21:44:51 2014
mdadm: partition table exists on /dev/sdh but will be lost or
       meaningless after creating array
Continue creating array? yes
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md3 started.

結果はうまくいってそう。

[122820.636434] md: bind
[122820.636659] md: bind
[122820.636855] md: bind
[122820.637074] md: bind
[122820.637307] md: bind
[122820.637532] md: bind
[122820.641063] md/raid: md3: device sdh operational as raid disk 5
[122820.641069] md/raid: md3: device sde operational as raid disk 4
[122820.641072] md/raid: md3: device sdc operational as raid disk 3
[122820.641075] md/raid: md3: device sdb operational as raid disk 2
[122820.641078] md/raid: md3: device sdd operational as raid disk 1
[122820.641080] md/raid: md3: device sdg operational as raid disk 0
[122820.642333] md/raid: md3: allocated 8606kB
[122820.642410] md/raid: md3: raid level 6 active with 6 out of 8 devices, algorithm 2
[122820.642415] RAID conf printout:
[122820.642419]  --- level:6 rd:8 wd:6
[122820.642421]  disk 0, o:1, dev:sdg
[122820.642424]  disk 1, o:1, dev:sdd
[122820.642426]  disk 2, o:1, dev:sdb
[122820.642428]  disk 3, o:1, dev:sdc
[122820.642430]  disk 4, o:1, dev:sde
[122820.642432]  disk 5, o:1, dev:sdh
[122820.642557] created bitmap (22 pages) for device md3
[122820.648666] md3: bitmap initialized from disk: read 2 pages, set 44711 of 44711 bits
[122820.678865] md3: detected capacity change from 0 to 18002749685760
[122821.015625] XFS (md3): Mounting V4 Filesystem
[122821.363476] XFS (md3): Starting recovery (logdev: internal)
[122823.302916] XFS (md3): Ending recovery (logdev: internal)

手動でマウントする前に、勝手にマウントされた。
正しくデータが読めている。

データが読めるので、おとなしくバックアップ用のHDDに大事なデータからバックアップ中。

バックアップが終わったら、残りの2台を追加してRAID6構成に戻す予定。
8台ではなく6台で再構成したのは、resyncが走るのを嫌って。間違った構成でresyncが走ると、もう戻せなそうだったから。
resyncが走らずアレイ構成できるギリギリの台数で縮退運転。
何はともあれよかった。

まとめ

行ったこと。

  • SMARTの確認
  • mdadm -A(assemble)による復旧
  • mdadm -EによるEventsの確認
  • dd, losetupを使ってループデバイスでmdadm -C(--create)を実験
  • ループデバイス上でmdadm -Cによる再構成
  • ループデバイス上でmdadm -Cによって作成されたアレイのメタデータをmdadm -Eで確認してバックアップと比較
  • ループデバイス上でmdadm -Cによる再構成をデータオフセットを指定して行う
  • 物理デバイス上でmdadm -Cによる再構成
  • 内部データのバックアップ

今後行うこと。

  • 縮退時にメールを飛ばす
  • バックアップをデイリーかウィークリーで組む
  • 裸族の集合住宅+eSATA構成を今後どうするか検討

補足

復旧天使というRAID6構成にもXFSにも対応するソフトがあるらしく、より事態が悪くなった場合はこれを購入することを考えた。

参考文献

462 :login:Penguin:2011/05/28(土) 17:48:01.24 ID:17piUe8k
>>460
-A sd[bcd]1が無理なら--createする時に縮退で組めば
resyncが発生せずにメタデータ上書きだけでデータ本体はそのまま残る。
--createするときはチャンクサイズとかレイアウトとかも要設定。
まずは仮想マシンで手順とか確認。

Docker for WindowsでRailsチュートリアルを行った作業ログ

MacBook ProのBootcampで仮想化がオフ

再起動してMacに入り「起動ディスク」画面を開いてBOOTCAMPのHDDを選択して再起動する。

『仮想ハード ディスクがある記憶域は、仮想ハード ディスクの共有をサポートしていません。』というエラー

『仮想ハード ディスクがある記憶域は、仮想ハード ディスクの共有をサポートしていません。』というエラーが出て
Hyper-VマネージャーでもDocker for Windowsでも上手く進まなかった。

Docker for Windowsをいったん削除して、
Windowsの機能』からHyper-Vを無効にして再起動後に再度Hyper-Vを有効にして
Docker for Windowsを再インストールするとエラーが出なくなった。

Windowsのボリュームをマウントできない

設定画面にてShared DrivesのCをチェックしてパスワード入れたが動かない。
Docker for WindowsのStable版を入れていたので、Beta版のmsiを落としてアップデートするとマウントできるようになった。

docker公式のQuickstart: Docker Compose and Railsをやってみる

https://docs.docker.com/compose/rails/ の手順通りに進めてみる。

途中、現時点の Docker for Windows の docker-compose では、docker-compose run ...を実行することができないため、rails newすることができない。

C:\Users\diffshare\docker\rails>docker-compose --version
docker-compose version 1.8.0, build d988a55

C:\Users\diffshare\docker\rails>docker-compose run web rails new . --force --database=postgresql --skip-bundle
ERROR: Interactive mode is not yet supported on Windows.
Please pass the -d flag when using `docker-compose run`.

docker-compose run -d ...という形では実行できるが、標準出力を見ることができないため面倒である。

幸いなことに docker run ... は動作をするので、そちらを用いて解決を行える。

C:\Users\diffshare\docker\rails>docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
rails_web              latest              5a76ef9eaa8d        27 minutes ago      865.2 MB

前述のURLのとおり、docker-compose buildを行っていると、ディレクトリ名+サービス名(ここではrails_web)でイメージが作成されているので、
そのイメージを用いてrails newする。

C:\Users\diffshare\docker\rails>docker run --rm -v %cd%:/myapp rails_web rails new . --force --database=postgresql --skip-bundle
       exist
      create  README.md
      create  Rakefile
      create  config.ru
      create  .gitignore
       force  Gemfile
      create  app
      create  app/assets/config/manifest.js
      create  app/assets/javascripts/application.js
      create  app/assets/javascripts/cable.js
      create  app/assets/stylesheets/application.css
      create  app/channels/application_cable/channel.rb
      create  app/channels/application_cable/connection.rb
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/jobs/application_job.rb
      create  app/mailers/application_mailer.rb
      create  app/models/application_record.rb
      create  app/views/layouts/application.html.erb
      create  app/views/layouts/mailer.html.erb
      create  app/views/layouts/mailer.text.erb
      create  app/assets/images/.keep
      create  app/assets/javascripts/channels
      create  app/assets/javascripts/channels/.keep
      create  app/controllers/concerns/.keep
      create  app/models/concerns/.keep
      create  bin
      create  bin/bundle
      create  bin/rails
      create  bin/rake
      create  bin/setup
      create  bin/update
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/secrets.yml
      create  config/cable.yml
      create  config/puma.rb
      create  config/spring.rb
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/application_controller_renderer.rb
      create  config/initializers/assets.rb
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/cookies_serializer.rb
      create  config/initializers/cors.rb
      create  config/initializers/filter_parameter_logging.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/new_framework_defaults.rb
      create  config/initializers/session_store.rb
      create  config/initializers/wrap_parameters.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  lib
      create  lib/tasks
      create  lib/tasks/.keep
      create  lib/assets
      create  lib/assets/.keep
      create  log
      create  log/.keep
      create  public
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/apple-touch-icon-precomposed.png
      create  public/apple-touch-icon.png
      create  public/favicon.ico
      create  public/robots.txt
      create  test/fixtures
      create  test/fixtures/.keep
      create  test/fixtures/files
      create  test/fixtures/files/.keep
      create  test/controllers
      create  test/controllers/.keep
      create  test/mailers
      create  test/mailers/.keep
      create  test/models
      create  test/models/.keep
      create  test/helpers
      create  test/helpers/.keep
      create  test/integration
      create  test/integration/.keep
      create  test/test_helper.rb
      create  tmp
      create  tmp/.keep
      create  tmp/cache
      create  tmp/cache/assets
      create  vendor/assets/javascripts
      create  vendor/assets/javascripts/.keep
      create  vendor/assets/stylesheets
      create  vendor/assets/stylesheets/.keep
      remove  config/initializers/cors.rb

そのまま作業を続けていくと、

$ docker-compose run web rake db:create

の部分が実行できない。docker run で実行する場合、コンテナをリンクする必要がある。

docker-compose buildおよびdocker-compose up -d後に次のコマンドでリンクするための調査を行う。

C:\Users\diffshare\docker\rails>docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
0fe39974801f        rails_web           "bundle exec rails s "   4 seconds ago       Up 2 seconds        0.0.0.0:3000->3000/tcp   rails_web_1
85dddc1e2f8d        mysql               "docker-entrypoint.sh"   46 minutes ago      Up 3 minutes        3306/tcp                 rails_db_1

C:\Users\diffshare\docker\rails>docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f894b76071b8        bridge              bridge              local
287217ca2bdd        docker_default      bridge              local
c30e18497d80        host                host                local
c017f8146f82        none                null                local
4e65602bd863        rails_default       bridge              local

まず、docker psでrails_webの名前を調べる。ここではrails_web_1となっている。
次にdocker networkでコンテナが所属するネットワークを調べる。ここではrails_defaultとなっている。

C:\Users\diffshare\docker\rails>docker run --rm -ti -v %cd%:/myapp --link rails_db_1:db --net rails_default rails_web bash
root@128cbb9d3ce1:/myapp# ping db
PING db (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: icmp_seq=0 ttl=64 time=0.076 ms
64 bytes from 172.19.0.2: icmp_seq=1 ttl=64 time=0.101 ms
^C--- db ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.076/0.088/0.101/0.000 ms
root@128cbb9d3ce1:/myapp#
root@128cbb9d3ce1:/myapp# rake db:create
Created database 'myapp_development'
Created database 'myapp_test'

最初に db エイリアスへの通信が行えるかどうかを確認し、その後、rake db:create を行う。

データベースの構築ができたので、localhost:3000にブラウザからアクセスすれば見えるはずである。

docker run使わずに素直にdocker-compose run -dした方がいいのかもしれない。

Docker公式のrails構築法では、Gemfileを更新するごとにdocker-compose buildを実行する必要があり、bundle installに時間がかかる。
bundle関係は別コンテナとしてリンクする方法をとるのが良いらしい。

(解決)MacBook AirのBootcamp領域をWinclone 4.4でリストアしたが起動しなかった件

面倒なので箇条書きで。

  • MacBook Air 2012 mid、Windows 8.1
  • MacBook AirSSDをJetDriveに変更する過程でMacintosh HDの領域のみしかコピーできない雰囲気
  • Bootcamp領域をWincloneの最新版でイメージ化
  • Wincloneによるイメージ化の前に事前にCHKDSKを行うべきだが行わなかった
  • JetDriveにMacintosh HD領域のコピー完了、起動成功
  • Mac OSMavericksからYosemiteにアップデート
  • ディスクユーティリティにてJetDriveをパーティション分割、半分をBOOTCAMP領域にしFATでフォーマット
  • Wincloneを用いてBOOTCAMP領域にレストア、起動ディスクをBOOTCAMPに
  • BOOTCAMP領域からの起動、EFI Bootに名前が変わっている
  • Windowsの起動を試みる、Windows8.1の起動画面が表示されるがサインイン画面に入らず黒い画面のまま
  • 何度起動しても同じ状態、当然ながらF8キーでセーフモード入れず
  • 起動画面中に電源ボタン長押しで強制終了、エラー発生により起動オプション画面に入りセーフモードを選択する
  • セーフモードでは起動確認。ネットワーク利用もOK。
  • 「起動画面が表示されるがサインイン画面に入れない」ことからディスプレイ関係が怪しいと判断
  • バイスマネージャーからIntel HD Graphics 4000を無効にする
  • 再起動後、通常起動に成功する

続き

  • 再度、有効にすると起動画面後にサインイン画面が表示されない現象に戻る
  • 以前に購入して使っていた「玄人志向 USB3.0 グラフィックアダプタ DVI接続 バスパワー駆動 VGA-USB3.0/DVI」というUSB接続のディスプレイアダプタを接続すると表示されることが分かる
  • 表示された画面から、ディスプレイの検出を行っても、見つけてくれない

メモ

解決

  • 既存のWindowsMBR方式でブートしていた、Bootcampで普通にやるとMBR方式になる
  • Winclone 4.4でWindows 8を復元するとEFI方式の起動になる
  • EFI方式でWindowsを起動すると、ディスプレイアダプタのドライバ(Intel HD Graphics 4000)が有効になるとブラックアウトする

- ブラックアウト状態でもリモートデスクトップ接続は可能

  • ウィンドウズのくるくるの後にドライバが有効になる、そのタイミングでブラックアウトする
  • セーフモードで起動するとディスプレイアダプタのドライバが有効にならないのでブラックアウトしない、ドライバを無効にしても同様
  • EFIブートしようとしている場合、電源投入時にoptionキーを押しっぱなしにして出るブートセレクタのBOOTCAMP領域の文字列が「Windows」から「EFI Boot」に変わっている様子が見られる
  • DisplayLinkに罪はない
  • Winclone 4.4で復元したパーティションMBRにするには以下の方法で行う
    • Mac OS Xの言語を英語にする
    • WincloneのソースのBOOTCAMPパーティションをcontrolキーとoptionキーを押しながらクリックして、Make Legacy Bootableをクリックする


日本語の場合には表示されない

英語だと表示される

AirPlayでUbuntuから音声・動画を転送してAppleTVで再生するために使えるRubyGemsに関する考察

考察の背景

iPhoneMacなどからAppleTVに対してAirPlayと呼ばれる機能を用いてストリーミング再生することが可能である。AppleTVをテレビやアンプと接続しておくことで、動画コンテンツを大画面テレビで音声コンテンツを音楽アンプで容易に転送できるため、コンテンツに適した形態で消費することができる。また、iPhoneMacなど転送元から一時停止やシーク・音量などの操作が行えるため、それぞれのリモコンで操作する手間がなく良い。

しかしながら、iOSMacWindows上のiTunes以外では、AirPlayを利用することが容易ではない。サードパーティがAirPlayによる転送のためのアプリを販売している様子が見受けられる。その転送は画面転送であり動画・音声転送ではない(これについて調べたのは過去なので今は様子が変わっているかもし知れない)。

画面転送では問題が出る場合がある。

AirPlayではリソースのURL、例えばYoutubeの動画URLをAppleTVに渡し、AppleTVは直接Youtubeの動画URLを叩くことでダウンロードを行いながら再生する。この場合は、AppleTVがYoutubeの動画をダウンロードするだけの回線帯域の消費である。

それに対して画面転送では、例えばWindows PCにYoutubeから一旦ダウンロードを行い、再度AppleTVに転送するという経路を通るため、前述の手法の2倍の帯域が必要であり、かつオリジナルの動画ファイルではなく転送用に再エンコードし直したものを送ることになる。2倍の帯域が必要という点で手元のPCが、無線LAN、特に802.11gなどを使っている場合は状況によって足りなくなるときがある。そのようなときに、コンテンツを格納するサーバとAppleTVが有線経路によって直で通信してくれると助かる。

この理由から、Windows上のサードパーティのAirPlay転送では不満足であり、AirPlayのURLによる再生を行う方法がコンテンツ消費としては望ましい。特にUbuntuの入ったサーバ上で実行して転送できると、なお良い。

airplayとそれを使ったCUIアプリ

AirPlayによるURLの再生を行う方法は、RubyGemsの中の1つairplayによって開拓され、airplayを用いたアプリケーションがいくつか登場している。これらのアプリはGoogle検索ではランクが高くなく、見つかりにくいので、ここに記しておく。アプリはUbuntu上でのみ検証し、全て動作を確認した。

AirPlayを活用するgemアプリケーションが用いる基本ライブラリはairplayである。

airplayライブラリを使った再生支援のgemは今のところ3つ知っている。

gem installしたりapt-get installしたりする必要がある。詳しい方法については、githubの各レポジトリを参照されたし。

airplayアプリの注意すべき点

これらの3つのアプリを使う上でいくつか注意点があるので書いておく。

  • airplay-cliおよびairplayerはavahiがちゃんと動いていないと動作しない
    • エラーは下の通り

DNSSD operation failed with unrecognized error code: -65537 (DNSSD::UnknownError)

      • このエラーが出た場合、avahiが起動しているか確認する
      • Ubuntuの場合、起動していないときがある。/etc/default/avahi-daemon ファイル内の AVAHI_DAEMON_DETECT_LOCAL=1 を AVAHI_DAEMON_DETECT_LOCAL=0 にして sudo start avahi-daemon すると起動する。この問題、すげー悩んだ。
    • airplay-cliを試してみて駄目だったらairplayerのREADME参考にapt-getした方が良い(と思う、多分、これについて確認していない)
  • airplay-cliやairplayerではローカルの動画ファイルを再生できない
    • airplayではローカルに存在する動画の転送は、ローカルにHTTPサーバを立ててAppleTVにそこにアクセスさせてダウンロードさせる方法を採用している
    • airplay-cliやairplayerでは、ローカルのサーバはairplayライブラリ経由でreel https://github.com/celluloid/reelを使う
    • なぜかRackサーバがreelだと起動しないのでwebrickに変更すると起動する

airplay-1.0.3/lib/airplay/server.rb:

module Airplay
  class Server
    include Celluloid

    attr_reader :port

    def initialize
      @port = Airplay.configuration.port || find_free_port
      @logger = Airplay::Logger.new("airplay::server")
      @server = Rack::Server.new(
        server: :reel,
        Host: private_ip,

module Airplay
  class Server
    include Celluloid

    attr_reader :port

    def initialize
      @port = Airplay.configuration.port || find_free_port
      @logger = Airplay::Logger.new("airplay::server")
      @server = Rack::Server.new(
        server: :webrick,
        Host: private_ip,

にする。何故、reelだと動かないのかについては調べていない。バージョン依存の問題かもしれない。
reel (0.5.0), ruby (1.9.3-p194), airplay (1.0.3)だが。

airplayアプリを改造する

機能的にはairstreamのシークとairplayerのyoutube直再生がいい感じなので、どちらか好きな方を改造して使うと消費が捗る。

自分でairplayアプリを書く

airplayライブラリを使ったCUIを自分で書く場合も簡単で、

#!/usr/bin/env ruby
require 'airplay'
player = Airplay.devices.first.play "./video.mp4"
sleep 120

とかやれば、動く。

さいごに

airplayライブラリ書いた人の苦労、凄いと思うのでHUGしてあげて欲しい。

こちらからは以上です。

rubymotion検討とvimでcocoapodsの補完(メソッド名とクラス名)

Swiftが発表されたすぐ後にrubymotionを購入し数日、経過した。
ネイティブアプリに関してもObjective-CとRubymotionの双方について1週間くらいチュートリアルなどを試して得られた、rubymotionに関する知見を書く。

Android開発についてはまったく知らない。

  • rubymotionはObjective-Cの代替手段と考える
    • Objective-Cの書き方が好きになれない場合に検討する
  • rubymotionやSwiftではなく、TitaniumかXamarinかCordovaを利用するべきシーン
  • rubymotionできればCocoa APIに詳しくなっているはずなので、Swiftでも困らないはず
  • rubymotionはCocoa APIにlock-inされるので、それを嫌う場合は前述の3種から選ぶ。
    • Titaniumはより複雑なことをしたい、もしくはパフォーマンスに問題ある箇所が出たならネイティブモジュールを書いた方が良い
      • そうすると結局はネイティブのAPIを覚えることになる
      • それでもTitaniumを使うことで手数が減るかどうか、のトレードオフ
  • rubymotionはAndroidにも対応するようだが、抽象化はライブラリ次第?
  • rake
    • rakeコマンドを叩いたときが快感、rake deviceも良い
    • gem追加すれば、rake ib:openでinterface builderも開ける。驚き

補完

  • CocoaAPIを利用する場合、補完がないと初心者は厳しい
    • 長いクラス名、メソッド名
  • メソッド名の候補を表示する際に型を考慮してより候補を絞る
  • 明示的に型を指定するObjective-Cに対して、補完は弱くなるはず
    • Rubyでは型を推定してメソッドの補完を呼び出す必要があるので、工夫が必要。RSenseがそれを行っているのか?
    • Objective-Cでは先頭にヘッダファイルを書くので、ヘッダファイル経由で補完対象を呼び出しにいける
    • SwiftはRubyと同様の理由で補完が当初から存在していない?
  • 現状のRubymotion(Ruby)の開発ではどうしているのか?

rubymotionでCocoaPodsも補完したい

ReactiveCocoaを使いたいがクラス名とメソッド名がすぐに出てこない。
書き始めれば覚えてしまうのかもしれない。リファレンスを見るのがだるい。

どうにか補完でがんばる。

メソッド名の補完
desc "Generate ctags"
task :ctags2 do
  tags_file = 'tags'
  config = App.config
  if !File.exist?(tags_file) or File.mtime(config.project_file) > File.mtime(tags_file)
    files = config.bridgesupport_files + config.vendor_projects.map { |p| Dir.glob(File.join(p.path, '*.bridgesupport')) }.flatten + config.files.flatten
    files << "./vendor/Pods/build-iPhoneSimulator/Pods.bridgesupport"
    ctags = File.join(config.bindir, 'ctags')
    config = File.join(config.motiondir, 'data', 'bridgesupport-ctags.cfg')
    sh "#{ctags} --options=\"#{config}\" #{files.map { |x| '"' + x + '"' }.join(' ')}"
  end
end
    • 前述のgistでスニペットを作る
      • rac...なんたらなメソッドが追加されていることを確認する
    • このままではクラス名が補完されないので辞書を作る
クラス名の補完
  • 前述のgistを改変する
#!/usr/bin/env ruby
require 'FileUtils'

words = []
File.read('tags').each_line do |line|
  next unless line.match /^[A-Z]\w+[^:]\t/
  line =~ /(^[^:\t]*)\t/
  words << $1
end
words.uniq!
File.open('rubymotion.dict', 'w') do |f|
  words.each do |word|
    f.write word+"\n"
  end
end
      • $HOME/.vim/dict あたりに生成されたファイルをつっこむ
      • .vimrcにてneocomplcacheを使っている。そのプラグインの方法でrubyファイルを読み込んだときの辞書ファイルを指定する
let g:neocomplcache_dictionary_filetype_lists = {
  \ 'ruby' : $HOME . '/.vim/dict/rubymotion.dict'
  \ }
    • UIWindowとかRACSignalとか書いて補完されることを確認する

この方法で未だコードを書き始めていないので便利かどうかは分からない。
別のプロジェクトにて追加していないcocoapodsの補完が出てしまう件については、我慢する。