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の再構成ができない
新しい筐体・マザーボードに乗せ換えて、新しいSSDにUbuntu 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構成の再作成を行うには、デバイスの順番が重要であり、これを間違うとデータが壊れる。
あらかじめ、以下のコマンドを実行して、何番のデバイスだったのかを確認する。
# 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 AirのSSDをJetDriveに変更する過程でMacintosh HDの領域のみしかコピーできない雰囲気
- Bootcamp領域をWincloneの最新版でイメージ化
- Wincloneによるイメージ化の前に事前にCHKDSKを行うべきだが行わなかった
- JetDriveにMacintosh HD領域のコピー完了、起動成功
- Mac OSをMavericksから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接続のディスプレイアダプタを接続すると表示されることが分かる
- 表示された画面から、ディスプレイの検出を行っても、見つけてくれない
メモ
- Boot Camp 5.0; Windows 8; CODE 43 on Intel HD Graphics 4000
- [Winclone]BootcampのWindows8の容量を変更したかったトラブル
解決
- 既存のWindowsはMBR方式でブートしていた、Bootcampで普通にやるとMBR方式になる
- Winclone 4.4でWindows 8を復元するとEFI方式の起動になる
- EFI方式でWindowsを起動すると、ディスプレイアダプタのドライバ(Intel HD Graphics 4000)が有効になるとブラックアウトする
- ブラックアウト状態でもリモートデスクトップ接続は可能
AirPlayでUbuntuから音声・動画を転送してAppleTVで再生するために使えるRubyGemsに関する考察
考察の背景
iPhoneやMacなどからAppleTVに対してAirPlayと呼ばれる機能を用いてストリーミング再生することが可能である。AppleTVをテレビやアンプと接続しておくことで、動画コンテンツを大画面テレビで音声コンテンツを音楽アンプで容易に転送できるため、コンテンツに適した形態で消費することができる。また、iPhoneやMacなど転送元から一時停止やシーク・音量などの操作が行えるため、それぞれのリモコンで操作する手間がなく良い。
しかしながら、iOSやMac、Windows上の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
- https://github.com/elcuervo/airplay
- Raspberry PI上でインテグレーションテストやっているらしい
airplayライブラリを使った再生支援のgemは今のところ3つ知っている。
- airplay-cli
- CUIによる再生
- airplayの参照実装をairplayライブラリ自体が提供している
- https://github.com/elcuervo/airplay
- airplayer
- CUIによる再生
- youtube-dlという別のプログラムを活用することで、youtubeの動画を直接再生できるようにしている
- https://github.com/Tomohiro/airplayer
- airstream
- CUIによる再生
- airplay gem側のavahiによる解決を行わないためavahiが起動していなくても利用できる反面、AppleTVのIPアドレスを自分で調べて自分で指定する必要がある
- シークに対応している
- https://github.com/unused/airstream
gem installしたりapt-get installしたりする必要がある。詳しい方法については、githubの各レポジトリを参照されたし。
airplayアプリの注意すべき点
これらの3つのアプリを使う上でいくつか注意点があるので書いておく。
- airplay-cliおよびairplayerはavahiがちゃんと動いていないと動作しない
- エラーは下の通り
DNSSD operation failed with unrecognized error code: -65537 (DNSSD::UnknownError)
- 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種から選ぶ。
- rubymotionはAndroidにも対応するようだが、抽象化はライブラリ次第?
- rake
- rakeコマンドを叩いたときが快感、rake deviceも良い
- gem追加すれば、rake ib:openでinterface builderも開ける。驚き
補完
- CocoaのAPIを利用する場合、補完がないと初心者は厳しい
- 長いクラス名、メソッド名
- メソッド名の候補を表示する際に型を考慮してより候補を絞る
- インテリセンス(Visual Studio, RubyMine)
- オムニ補完(Vim)
- 明示的に型を指定するObjective-Cに対して、補完は弱くなるはず
- Rubyでは型を推定してメソッドの補完を呼び出す必要があるので、工夫が必要。RSenseがそれを行っているのか?
- Objective-Cでは先頭にヘッダファイルを書くので、ヘッダファイル経由で補完対象を呼び出しにいける
SwiftはRubyと同様の理由で補完が当初から存在していない?
- 現状のRubymotion(Ruby)の開発ではどうしているのか?
- 暗記
- スニペット
- インテリセンス(RubyMine)
rubymotionでCocoaPodsも補完したい
ReactiveCocoaを使いたいがクラス名とメソッド名がすぐに出てこない。
書き始めれば覚えてしまうのかもしれない。リファレンスを見るのがだるい。
どうにか補完でがんばる。
メソッド名の補完
- snipmate-snippets-rubymotion
- https://github.com/rcyrus/snipmate-snippets-rubymotion
- 本質は以下のgistでスニペットを作成する箇所
- https://gist.github.com/shayarnett/2652913
- rubymotionではrake ctagsでタグを出力できるのでそれを利用してスニペットを作成する手法
- まず rake ctags で CocoaPodsを参照するように変更する
- https://github.com/HipByte/RubyMotion/blob/8ad5261b1b622768ca64f0f5491d660fe54b0c0e/lib/motion/project.rb
- 上記URLを参考にしつつRakefileに以下を追加
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を改変する
#!/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の補完が出てしまう件については、我慢する。