d.sunnyone.org
sunnyone.org

ページ

ラベル Debian の投稿を表示しています。 すべての投稿を表示
ラベル Debian の投稿を表示しています。 すべての投稿を表示

2015-12-06

HDDが故障した話 (QNAP TS-219PにDebian jessieをインストールする)

多分5年以上使っていたNAS, TS-219PについているHDDの2台のうち片方が壊れた。Software RAID1構成なので、交換してリビルドすればいいという話だったはずなのだが、長期戦になってしまった。

今回は時系列に沿って。日数はフィクションです。仕事の話じゃなくてよかった(仕事だったらもっと慎重だったろうから、こんなんにならないと思うけど)。

1日目: 拡張できるはずだったのに

もともと2TB x 2本の構成だった。もちろん2TBを買ってきて取り替えればよい。だが、容量を拡張できる機能があることがわかったので、2015年現在のGB単価的(→サハロフの秋葉原レポート)に4TBにしようと思って4TBを2本買ってきた。

もちろん、時代的に4TB扱えなくてもそういうものかという感じな気がするので、compatibility listを見て4TBに対応していることを確認して買った。

ところが、4TBを差しても認識しない。ファームウェアがだいぶ古いので、アップグレードしてみることにする。

2日目: ファームウェアアップグレード

ファームウェアアップデートすると、今度は生きている2TBのディスクまでWeb管理画面から見えなくなってしまった。sshログインを使って、cat /proc/filesystemsを見ると、ext4がいない。ファームウェアの更新がうまくいかなかったのかなと思って再度更新をかけようとすると、バージョンを確認しろという旨のエラーが出て受け付けてもらえない。

バージョンがとんでもなく変わっていたので、変化に耐えられなかったのであろう。もうだめだ。ブラックボックスな独自OSで戦うのはここで限界。汎用OSで使えるものを探そう。

3日目: Debianインストール チャレンジ

Debianが使えないかなと調べてみると、Martin Michlmayr さんという方がまとめてくれている。手順まで詳しく載っており、これは戦えそうである。
Debian on QNAP TS-21x/TS-22x

インストール手順はInstalling Debian on QNAP TS-21x/TS-22xにある通り、

まずフラッシュ領域をバックアップする(後にわかることだが、これは大変に重要であり、絶対に避けてはいけない。)

vfatもマウントできない状態なので、別のマシンでUSBメモリをext2でフォーマットしておいたものを挿入し、catでコピーする。
mount /dev/sdX1 /tmp/usb
cd /tmp/usb
cat /dev/mtdblock0 > mtd0
cat /dev/mtdblock1 > mtd1
cat /dev/mtdblock2 > mtd2
cat /dev/mtdblock3 > mtd3
cat /dev/mtdblock4 > mtd4
cat /dev/mtdblock5 > mtd5
cd
umount /tmp/usb

そうしたら、カーネルやインストーラの入ったinitrdをダウンロードし、flash-debianスクリプトを起動する。
cd /tmp
busybox wget http://ftp.debian.org/debian/dists/stable/main/installer-armel/current/images/kirkwood/network-console/qnap/ts-219/initrd.gz
busybox wget http://ftp.debian.org/debian/dists/stable/main/installer-armel/current/images/kirkwood/network-console/qnap/ts-219/kernel
busybox wget http://ftp.debian.org/debian/dists/stable/main/installer-armel/current/images/kirkwood/network-console/qnap/ts-219/flash-debian
busybox wget http://ftp.debian.org/debian/dists/stable/main/installer-armel/current/images/kirkwood/network-console/qnap/ts-219/model
sh flash-debian

リブートするよう促されるので、rebootした。
reboot

DHCPでアドレスが払い出されるので、そのアドレスに対してinstallerユーザでsshログインする。
$ ssh installer@192.168.1.XX

cursorsのUIが起動し、インストーラが開始する。あとは選べばよいだけ……のように見えた。

4日目: インストーラが途中で止まる

普通のDebianインストーラだと安心し進んでいくと、パッケージのインストールのプログレスバーが途中で止まってしまう。最初からやり直しても同じ。

何度かディスクの構成を変えながら試してみても変わらないので、もう一つinstallerユーザでsshし、shellを選び/var/logのログを見ていると「UUID ~ doesn't exist in /dev/disk/by-uuid」なるログが。

そのキーワードを基に検索してみると、こんなバグ報告を発見。
#791794 - INSTALL REPORT (Jessie on QNAP TS-420U)

どうやらmdでミラーを組んでしまうと、/dev/disk/by-uuidのIDが更新されず、flash-kernelという裏で動くmtdデバイスにカーネルイメージを書き込むツールが書き込みに失敗するらしい。このツールがエラー終了するのではなく、Ctrl+C待ちで止まってしまっているので、フロントのインストーラのプログレスが止まったままとなっていたようだ。

書いてある感じに、ディスクの構成が終わったタイミングでもうひとつssh接続し、shellに降りて
udevadm tigger
とすることで、進むようになった。

このバグで触れられていたために、mdで作られたRAIDミラーがdegradedだと、起動時にemergency shellに落ちるという恐怖のバグを発見。通常コンソールのないこのNASでは、sshできない状態に落とされるのは致命的である。

#784070 - mdadm Software RAID1 with GPT on Debian 8.0.0 amd64 - Does not mount/boot on disk removal

おすすめされる行為ではないが、sidには修正済みのパッケージがあったため、バージョンの変化やdependencyなどを見てsidから持ってきて入れた。実際に1本外して試したところ、きちんと立ち上がるようになっていた。

LVMを構成したり、NFSやSambaなどなどNASっぽいデーモンをインストールしたりする。Ansibleで作ったのでやりなおせる。

5日目: rsyncデータコピー待ち

USB接続した元々の2TB HDDからrsyncでデータをコピーする。たいへんに時間がかかるが、待つしかない。

6日目: 再起動したら……

データのコピーも終わり、デーモンの動作もOK, 念のため再起動を試しておく。

……立ち上がらない。コンソールがないので状況もわからない。

11/30: フラッシュ・リカバリ

Martinさんはリカバリの方法も書いてくれていたので、QNAP NASのリカバリの手順でインストーラを起動して中の様子を見てみることにする。

Recovery mode of QNAP TS-21x/TS-22x

TS-219Pのリカバリモードは、ブート時にtftpでリカバリイメージを取得し、フラッシュ領域を書き直す。

debian-installerを動作させるイメージを作るには、まずカーネルイメージにpaddingを加えて所定のサイズにする。
dd if=kernel of=kernel.pad ibs=2097152 conv=sync

あとはinitrd.gzと、もともとのmtdblockイメージを連結して作る。取っててよかったバックアップ!
cat mtdblock0 mtdblock4 mtdblock5 kernel.pad initrd.gz mtdblock3 > F_TS-219

このファイル名は、u-boot パラメータが格納されているmtdblock4に入っているので念のため確認しておく。
strings mtdblock4 | grep bootp_vendor_class

次に、適当なノートPCを使ってDHCPサーバ + TFTPサーバを立てる。Martinさんは普通にdhcpdで立てているようだが、dnsmasqはそのどちらの機能も備えており、さくっと立てることができた。

あとは、NASをdnsmasqを立てたノートPCと直結し、背面にあるLANコネクタの隣あたりにあるピンで押すリセットボタンを押しながら、電源ボタンを押して起動する。すると、ピー、ピーと短く鳴って起動する。

その時のコマンド・ログはこんな感じだった。
$ sudo dnsmasq --no-daemon --port=0 --interface=eth0 --domain=example.com \
  --dhcp-range=192.168.0.3,192.168.0.253,255.255.255.0,1h --dhcp-boot=F_TS-219 \
  --enable-tftp --tftp-root=`pwd`
dnsmasq: started, version 2.75 DNS disabled
dnsmasq: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop-detect inotify
dnsmasq-dhcp: DHCP, IP range 192.168.0.3 -- 192.168.0.253, lease time 1h
dnsmasq-tftp: TFTP root is /tmp/ts219
dnsmasq-dhcp: DHCPDISCOVER(eth0) 00:08:9b:XX:XX:XX
dnsmasq-dhcp: DHCPOFFER(eth0) 192.168.0.216 00:08:9b:XX:XX:XX
dnsmasq-dhcp: DHCPREQUEST(eth0) 192.168.0.216 00:08:9b:XX:XX:XX
dnsmasq-dhcp: DHCPACK(eth0) 192.168.0.216 00:08:9b:XX:XX:XX
dnsmasq-tftp: sent /tmp/ts219/F_TS-219 to 192.168.0.216
--no-daemonで起動すると、わざわざtail -fしなくてもログが追え便利であった。

10分程待つと再びピー、ピーと音がなり、再起動される。すると、無事に同じようにinstaller@で接続できるようになった。

インストーラが起動したら、ディスクの設定画面まで進めたあと、別のssh接続を行い、shellに降りる。shellが起動したら、以下のようにchrootを実行して、ディスク上の環境を得る。

mount /dev/md0 /mnt/md0
mount --bind /dev /mnt/md0/dev
mount --bind /proc /mnt/md0/proc
mount --bind /sys /mnt/md0/sys
chroot . bin/bash

fstabがおかしいかなと新しく作ったエントリをコメントアウトしたりした。終わったら、元のカーネルに戻すべくフラッシュする。
flash-kernel

rebootすると、無事起動した。原因についてははっきりわかっていないが、おそらく、fstabうんぬんではなく、USB接続したディスクをmdデバイスとして見せた状態でinitrdを更新してしまったために、変な情報を覚えられてしまったのかなと思っている。ディスクが見えなくなるから起動しなくなるかもよみたいなことを書いてあった記憶。

7日目: USBシリアルからコンソール出せれば便利じゃね?

ブートオプション変更すればUSBシリアルにコンソール出せるんじゃね?このデバイスはU-Boot使ってるからfw_setenvでブートオプション変更できるんじゃね?と思ったらやっぱりあった。

U-Boot tools for Debian ARM Linux in QNAP Server | Black God

ダメでもどうせフラッシュすればいいやーと思って書き換えてみることにする。

まずは設定。
$ cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00080000 00040000 "U-Boot"
mtd1: 00200000 00040000 "Kernel"
mtd2: 00900000 00040000 "RootFS1"
mtd3: 00300000 00040000 "RootFS2"
mtd4: 00040000 00040000 "U-Boot Config"
mtd5: 00140000 00040000 "NAS Config"
# vi /etc/fw_env.config
(書き込み)
# Configuration file for fw_(printenv/saveenv) utility for
# QNAP TS-119, TS-219 and TS-219P.

# MTD device name Device offset Env. size Flash sector size
/dev/mtd4 0x0000 0x1000 0x40000

確認。
# fw_printenv

ttyUSB0を使うように書き換え(コマンドはイメージです:注:このデバイスでのコンソールアクセスがない状態での書き換えはやってはいけません)
# sudo fw_setenv bootargs 'console=ttyS0,115200 root=/dev/ram initrd=0xa00000,0x900000 ramdisk=32768'

再びfw_printenvを実行してみると、書き換わっている。

いざ再起動……立ち上がらない。まぁいいや、リカバリならもう慣れた……リカバリ完了。立ち上がらない!?

8日目: カーネルビルドという選択肢

試しにPCでUSBシリアルを接続し、grubからconsole=ttyUSB0として起動しようとしてみると、起動しない。先にやっておくべきだった!

でもU-Bootのコンフィグが入っているのは先に見たようにmtd4。フラッシュイメージにはmtd4が入っている。直るはずだ!

とMartinさんのページをよく見てみると、こんな記述が。
During recovery mode, mtd0 (the boot loader), mtd4 (the boot loader configuration) and on some devices mtd5 (device configuration) are ignored
……なぜここを読み飛ばしてしまっていたのか。mtd4はリカバリでは戻らない。やってしまった……

U-Bootのコンソールを叩きにいけば直るはずなので、シリアルコンソールに接続してコマンドを叩けば直る。でも現状その接続はない。そこでもう一つの選択肢。設定されたbootargsで立ち上がるカーネルを作ればよい。

ということで、活躍していないsqueezeのarmelデバイスがあったので、これを使ってlinux-sourceをダウンロード。中に入っているはずのカーネルパッケージに含まれるconfigを見ると、どうもCONFIG_USB_SERIAL=mであるのが影響していそうだ。

ということで、=yになるようmake menuconfigでちょいちょいといじって、カーネルを作り直す。起動しない。linux-sourceからのカーネルビルドの手順にまったく沿っていないためか、そもそも元のconfigで作り直しても全然違うサイズになる。やり方が雑過ぎたようだ。

9日目: クロスビルド環境でのカーネルコンパイル(失敗)

make menuconfigを眺めていると、ブートオプションを強制するオプションがあった。.config的にはこんな感じである。
CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram initrd=0xa00000,0x900000 ramdisk=32768"
CONFIG_CMDLINE_FORCE=y

なおビルドについては、armelデバイスが古すぎるためか、一晩寝てもコンパイルが完了しない。これでは時間がかかりすぎるので、クロスビルドするしかないか、と思って適当なページを見ながら、適当なUbuntu 15.10のマシンを使ってコンパイルするも、コンパイルエラー。まともに環境を作ろうとすると大変そうなのでこのビルド方式はあきらめ。
How do I cross-compile the kernel on a Ubuntu host? - Raspberry Pi Stack Exchange

$ sudo apt-get install git ncurses-dev make gcc-arm-linux-gnueabi
(カーネルとconfigを配置/展開)
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- oldconfig
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- menuconfig
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- zImage

10日目: そもそもarmelをエミュレーションした環境でビルドする(途中)

そういえばx86なマシンでもqemu使えばarmel環境をエミュレーションできるんじゃね?ということで環境を作る。
qemu-debootstrapを使ってユーザモードQEMUで動くDockerイメージを作ってみる - ももいろテクノロジー

$ sudo apt-get install debootstrap qemu-user-static
$ sudo qemu-debootstrap --verbose --arch=armel --variant=buildd \
  --include=vim-tiny,less jessie rootfs-debian-armel http://http.debian.net/debian/
$ sudo chroot rootfs-debian-armel

今度こそjessieになったのでHowToRebuildAnOfficialDebianKernelPackageの手順を使ってビルドしてみる。armel指定の部分はこんな感じ。

# fakeroot make -f debian/rules.gen setup_armel_none_kirkwood
# fakeroot make -f debian/rules.gen binary-arch_armel_none_kirkwood binary-indep \
DEBIAN_KERNEL_JOBS=4

普通に進んでいたので、このままほっとけばできたのかもしれないが、4つコアを使っている感じがなく時間がかかりすぎて作業時間オーバー。とりあえず断念。

11日目: そしてシリアルコンソールへ

カーネルビルド方式では、リカバリまで含めての試行錯誤の1ターンがかかりすぎるので、ついにシリアルコンソールに手を出すことにした。ここで失敗するとハードウェア破壊を意味するので、あまりやりたくなかったのだ。

やりかたはMartinさんがピン配置を書いてくれているので、この通り接続する。
Serial console for QNAP TS-21x/TS-22x

コネクタはPHR-4というもので千石電商の2Fにあったので買ってケーブルとピンヘッダに差すコネクタをハンダ付けしてケーブルを作った。

RS-232Cレベルではなく、3.3Vなので昔買ったFT232RLの変換アダプタにつなげばよさそうだなーと思ったが、Raspberry Piのシリアルピン使えるんじゃね?とRasPiの存在を思いだし、RasPiが登場。TS-219P - RasPiをTx - Rx, Rx - Tx, GND - GNDで接続した。

RasPi側ピン
(https://www.raspberrypi.org/documentation/usage/gpio/)より

TS-219P側ピン

黄: Tx
黒: Vcc (接続しない)
赤: Rx
青: GND


シリアルポートの場所はここ。ケースは固いので開けたくなかったが、開けないと手が届かない。

RasPiは、ブートオプションconsole=に当該ポートが指定されていて使えないので、/boot/cmdline.txtを編集してconsole=ttyAMAの記述をトル。
http://elinux.org/RPi_Serial_Connection
console=パラメータの変更はまさに悩んでいる部分なので、こうさらっと変更できると複雑な気分。

あとは起動して、
$ cu -s 11200 -l /dev/ttyAMA0
として待つ。あとはTS-219Pをブートすればコンソールが現れるのでauto-bootを止める。あとはsetenv, saveしてブート。
         __  __                      _ _
        |  \/  | __ _ _ ____   _____| | |
        | |\/| |/ _` | '__\ \ / / _ \ | |
        | |  | | (_| | |   \ V /  __/ | |
        |_|  |_|\__,_|_|    \_/ \___|_|_|
 _   _     ____              _
| | | |   | __ )  ___   ___ | |_ 
| | | |___|  _ \ / _ \ / _ \| __| 
| |_| |___| |_) | (_) | (_) | |_ 
 \___/    |____/ \___/ \___/ \__|  ** LOADER **
 ** MARVELL BOARD: DB-88F6281A-BP LE 

U-Boot 1.1.4 (Jan  5 2009 - 12:58:51) Marvell version: 3.4.4

U-Boot code: 00600000 -> 0067FFF0  BSS: -> 00690DCC

Soc: MV88F6281 Rev 3 (DDR2)
CPU running @ 1200Mhz L2 running @ 400Mhz
SysClock = 400Mhz , TClock = 200Mhz 
(略)
Hit any key to stop autoboot:  0 
QNAP: Recovery Button pressed: 0
Marvell>> printenv
(略)
Marvell>> setenv bootargs console=ttyS0,115200 root=/dev/ram initrd=0xa00000,0x900000 ramdisk=32768
Marvell>> saveenv
Saving Environment to Flash...
................................................................
.
Un-Protected 1 sectors
Erasing Flash...
.
Erased 1 sectors
Writing to Flash... done
................................................................
.
Protected 1 sectors
Marvell>> printenv
baudrate=115200
(略)
bootargs=console=ttyS0,115200 root=/dev/ram initrd=0xa00000,0x900000 ramdisk=32768

Environment size: 1339/4092 bytes
Marvell>> boot
Unknown command 'uart1' - try 'help'
## Booting image at 00800000 ...
   Image Name:   
   Created:      2015-12-02  15:12:54 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1968432 Bytes =  1.9 MB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.

無事起動。これでちゃんと起動するDebian環境が得られた。

おわりに

USBシリアルでコンソールを見ようというのは本当に余計だった。

自分の環境ではこんな目にあってしまったが、今まで見てきたARMデバイスの中ではDebian officialで済む範囲が多いデバイスなので、Debianを入れてみるというのはアリだと思う。カーネルイメージは公式のものを使えなかったり、ファンコントロールは外部だったりといったことが多いが、これはどちらもofficialに含まれている。

もちろんメーカーの力は得られなくなるので、いわゆる自己責任で。新しく買ってきてというよりは、昔の保証切れてそうな箱でやってみるという感じがよいかとは思う。

2012-12-23

Linux boxにUSBストレージを接続したとき勝手に同期するようにする

同期とはなんだか難しそうだと思ったあなた!正しいと思います。

そんな「同期」ですが、今日の話は難しくありません。
簡単に書くと、udevデーモンにデバイス固有の設定を入れて、つないだときにrsyncを走らせましょうという話です。

必要なもの

  • 適当なLinux box(今回はDebian squeeze)
  • 適当なUSB storage
今回はSheevaPlugとKobo gloを利用。
udevは若干変わっているので、最近のUbuntuでも大丈夫だと思うが、RHEL(特に5)だとちょっとわからない。
ただし、GNOMEが動いていたりすると、そっちで勝手にマウントされそうなので、無効にしておいたほうがいいかも。

デバイスを特定する

つないだら、まずは普通にdmesgコマンドでログを見るか、fdisk -lでデバイスを調べる。
今回のkoboはsdaとして認識された。
(このSheevaPlugはルートがSDカードだからmmcblk0なのだけど、sdaがシステムになっているデバイスが多いと思うので、この下のコマンド達をパスまでコピペしないよう注意。)

/dev/sdaがデバイスだとわかったので、devadmコマンドのinfo -q path -n /dev/XXXを使って、sysfsでのパスを特定する。
$ sudo udevadm info -q path -n /dev/sda
/devices/platform/orion-ehci.0/usb1/1-1/1-1:1.0/host11/target11:0:0/11:0:0:0/block/sda

そうしたら、udevadmコマンドのinfo -p [パス] -aを使って、デバイスに関する情報を表示する。
(もちろん、この2つのコマンドは$()とかを使って1行で実行してもよい)
$ sudo udevadm info -p /devices/platform/orion-ehci.0/usb1/1-1/1-1:1.0/host11/target11:0:0/11:0:0:0/block/sda -a

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/platform/orion-ehci.0/usb1/1-1/1-1:1.0/host11/target11:0:0/11:0:0:0/block/sda':
    KERNEL=="sda"
    SUBSYSTEM=="block"
(略)
  looking at parent device '/devices/platform/orion-ehci.0/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}=="Self-powered"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="c0"
    ATTRS{bMaxPower}=="  2mA"
    ATTRS{urbnum}=="229"
    ATTRS{idVendor}=="2237"
    ATTRS{idProduct}=="4173"
    ATTRS{bcdDevice}=="0110"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="13"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Kobo"
    ATTRS{product}=="eReader"
    ATTRS{serial}=="XXXXXXXXXXXXX"
(略)

  looking at parent device '/devices/platform/orion-ehci.0':
    KERNELS=="orion-ehci.0"
    SUBSYSTEMS=="platform"
    DRIVERS=="orion-ehci"
    ATTRS{modalias}=="platform:orion-ehci"

  looking at parent device '/devices/platform':
    KERNELS=="platform"
    SUBSYSTEMS==""
    DRIVERS==""
重要なのは「ATTRS{serial}」というところ。これをキーにデバイスを決定する。
ただし、万が一でも誤爆しないよう念の為「ATTRS{manufacturer}」と「ATTRS{product}=="eReader"」も使うことにした。なので、今回使う情報は以下。
  • ATTRS{manufacturer}=="Kobo"
  • ATTRS{product}=="eReader"
  • ATTRS{serial}=="XXXXXXXXXXXXX"

同じ種類のデバイスをひとつしか持っていないときは、USBデバイスの種類を特定するかぎである「ATTRS{idVendor}」「ATTRS{idProduct}」
を使ってもよいと思う。

udevの設定をする(1) - デバイスに名前をつける

まずは、調べた情報を使って、/dev以下に勝手なシンボリックリンクを置く。今回はkoboなので/dev/kobo。

/etc/udev/rules.dに以下のように設定ファイルを配置すればOK。

/etc/udev/rules.d/92-kobo.rules
KERNEL=="sd*", ACTION=="add", \
  ATTRS{manufacturer}=="Kobo", ATTRS{product}=="eReader", \
  ATTRS{serial}=="XXXXXXXXXXXXX" \
  NAME="%k", SYMLINK="kobo"

あとは、デバイスをつなぐと、/dev/koboが作られる。
$ ls -l /dev/kobo /dev/sda
lrwxrwxrwx 1 root root      3 Dec 23 18:19 /dev/kobo -> sda
brw-rw---- 1 root floppy 8, 0 Dec 23 18:19 /dev/sda

udevadmのman pageを見ると「The udev daemon detects changes automatically」って書いてあるけど、もし認識しなかったら以下のコマンドを叩いてみるといいかも。
$ sudo udevadm control --reload-rules

fstabの設定

/dev/koboがつながったときに、マウントできるようにする。

まずマウントするためのディレクトリを作る。
$ sudo mkdir /media/kobo

koboの内部ストレージは、パーティションなしでデバイスまるまるマウントすればいいので、以下のような行を
/etc/fstabに追加する。

/dev/kobo        /media/kobo     vfat   rw,codepage=932,iocharset=utf8 0 0

マウントできることを確かめる。
$ sudo mount /media/kobo
$ df -h

ディスク容量が表示されたら、umountしてデバイスを外す(本当は切り離しもやったほうがいいんだろうけど…)
$ sudo umount /media/kobo

自動同期するスクリプトを用意する

マウントしてrsyncし、アンマウントしてメールを送るだけの簡単なスクリプトを用意して、
/usr/local/bin/synckobo.shに配置する。


デバイスをつないで、マウントされてない状態で、スクリプトを叩いて同期できたらOK.
見慣れない"--modify-window=1"については、「rsync FAQ」を参照。vfatならつけておくのが幸せだと思う。

udevの設定をする(2) - 接続時にスクリプトを実行する

さきほど作った設定ファイルに「RUN」を追加する。

KERNEL=="sd*", ACTION=="add", \
  ATTRS{manufacturer}=="Kobo", ATTRS{product}=="eReader", \
  ATTRS{serial}=="XXXXXXXXXXXXX" \
  NAME="%k", SYMLINK="kobo", \
  RUN="/usr/local/bin/synckobo.sh"

接続して同期されれば成功!

2012-03-12

SheevaPlug復旧の巻(debootstrapによる環境構築とSDカード向け設定)

前エントリの通り、SheevaPlugの/だったSDカードが壊れてしまったので、構築しなおすことにする(muninで監視情報を書き込み続けたらそれは壊れるよな、と思いつつ同じ環境を作る)

<準備>
・armelなDebianの入ったデバイス
・SDカードリーダ/ライタ
・SDカード(以下では16GBを利用)

1. パーティション作成
普通にパーティションを切る(以下では/dev/sdbにつながったと想定)
# fdisk /dev/sdb
 以下のように作った。
/dev/sdb1 100M  (/boot用)
/dev/sdb2 10G  (/用)
/dev/sdb3 1G  (swap用)
/dev/sdb4 残り (/home用)

2. ファイルシステム作成
# mkfs.ext3 /dev/sdb1
# mkfs.ext4 -O ^has_journal /dev/sdb2
# mkswap /dev/sdb3
# mkfs.ext4 -O ^has_journal /dev/sdb4
 どうやらSDカードではext4が速いらしいので、/boot以外に採用。
 そしてジャーナルなしが速いらしいので、ジャーナルは無効化する。
電源断に備えても、書き込みが増えて壊れては意味が無いしね。
 /bootはU-Bootが読めなかったら困るので、ext3のままにしておく。
# tune2fs -l /dev/sdb1 | grep features
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype sparse_super
# tune2fs -l /dev/sdb2 | grep features
Filesystem features:      ext_attr resize_inode dir_index filetype extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
 has_journalがなくなっていることを確認。

3.  debootstrap
debootstrapで初期環境を作る。同一アーキテクチャなので、--foreign と--second-stageに分割する必要はない。
# mount /dev/sdb2 /mnt
# debootstrap --arch=armel --include=linux-image-2.6-kirkwood,module-init-tools,udev,netbase,net-tools,ifupdown,iproute,whiptail,vim-basic squeeze /mnt http://ftp.jp.debian.org/debian/
4. 諸設定
# cd /mnt 
(ファイルシステム設定)

# vi etc/fstab

~~~
#              
proc            /proc           proc    defaults        0       0
/dev/mmcblk0p2 /               ext4    errors=remount-ro,commit=21600,noatime 0       1
/dev/mmcblk0p1 /boot           ext3    defaults        0       2
/dev/mmcblk0p3  none           swap    sw              0       0
/dev/mmcblk0p4 /home           ext4    defaults        0       2
tmpfs          /tmp tmpfs defaults 0 0
~~~
(ホスト名設定)
# echo myhost > etc/hostname
(ネットワーク設定)
# vi etc/network/interfaces
~~~
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
iface eth0 inet static
  address 192.168.1.100
  netmask 255.255.255.0
  network 192.168.1.0
  broadcast 192.168.1.255
  gateway 192.168.1.254
  dns-nameservers 192.168.1.254
  dns-search localdomain.local
~~~
 (コンソール設定)
# vi etc/inittab
一部編集
~~~
##1:2345:respawn:/sbin/getty 38400 tty1
##2:23:respawn:/sbin/getty 38400 tty2
##3:23:respawn:/sbin/getty 38400 tty3
##4:23:respawn:/sbin/getty 38400 tty4
##5:23:respawn:/sbin/getty 38400 tty5
##6:23:respawn:/sbin/getty 38400 tty6
T0:2345:respawn:/sbin/getty -L ttyS0 115200 linux
~~~

てな感じ。

5. おまじない
/etcにあまり書かないようにする。
# ln -s /dev/null etc/blkid.tab
# ln -s /proc/mounts etc/mtab

作っているホストのNIC情報でeth0が固定されてしまうっぽいので、消しておく。
# echo > /etc/udev/rules.d/70-persistent-net.rules
あまり書かないように設定。
# vi etc/sysctl.conf
~~~追記~~~
vm.dirty_background_ratio = 30
vm.dirty_ratio = 60
vm.dirty_expire_centisecs = 500000
vm.dirty_writeback_centisecs = 600000
~~~
6. パスワード設定
# chroot /mnt /bin/bash
# passwd root
7. ブートイメージの作成
chrootの流れで。
# apt-get update
# apt-get install uboot-mkimage
# cd /boot
# mkimage -A arm -O linux -T kernel  -C none -a 0x00008000 -e 0x00008000 \
  -n Linux-2.6.32-5 -d vmlinuz-2.6.32-5-kirkwood uImage
# mkimage -A arm -O linux -T ramdisk -C gzip -a 0x00000000 -e 0x00000000 \
  -n initramfs -d initrd.img-2.6.32-5-kirkwood uInitrd
8. リブート
終わったらいよいよSDカードを差してリブート。U-Bootのカウントダウンで止める。

9. U-Boot環境変数設定
printenvして、期待する値になっていなかったら、以下のようにセットしてしまう。

Marvell>> setenv bootargs_mmc 'console=ttyS0,115200 root=/dev/mmcblk0p2 rw'
Marvell>> setenv bootcmd_mmc 'mmcinit; ext2load mmc 0:1 0x01100000 /uInitrd; ext2load mmc 0:1 0x00800000 /uImage'
Marvell>> setenv bootcmd 'setenv bootargs $(bootargs_mmc); run bootcmd_mmc; bootm 0x00800000 0x01100000'
Marvell>> printenv
Marvell>> saveenv

終わったらbootする。

10. 起動後設定
# date
Thu Nov  5 21:59:39 UTC 1908
さすがにおかしすぎる・・・いったん設定する
# date 031100592012
dateコマンドでセットするときはmmddHHMMyyyyなんだよね。

あとはいつもの感じで設定。
(ロケール設定)
# apt-get install locales
# vi /etc/locale.gen
~~~
ja_JP.UTF-8 UTF-8
~~~
# locale-gen
(スタンダードパッケージをインストール)
# tasksel install standard
(タイムゾーン設定)
# dpkg-reconfigure tzdata
→Tokyo
あとはお好みでsudoを入れたり、openssh-serverを入れたりすれば使えるようになる。

【参考】
http://blog.bofh.it/debian/id_265
http://www.cyrius.com/debian/kirkwood/sheevaplug/install.html
http://d.hatena.ne.jp/yamanetoshi/20090114

よく知らないARMデバイスのU-Boot環境変数を読む

U-Bootはブートローダ。x86では似たようなことを違うUIでBIOSが担うのであまりピンとこないが、SPARCを使ったことある人なら、OpenBootのプロンプトを思い浮かべてもらえばピンとくると思う。

U-Bootの設定情報を維持している、U-Bootの環境変数を見るには、U-Bootを実行している間にprintenvすれば表示できるのだが、シリアルにアクセスできないデバイスを持っている人もいるはず。そこで、ここではOS(Linux)上から見る方法を取り上げる。

【正攻法】
fw_printenvというコマンドがあるので、これを使う。
1. インストール
  # apt-get install uboot-envtools

2. 設定
どこからか機器依存なデバイス情報を拾ってきて、/etc/fw_env.configに書く。
以下、SheevaPlugの場合
 /dev/mtd0 0xa0000 0x20000 0x20000
ちなみに0xa0000でない場合もあるらしい。

3. 実行 
$ sudo fw_printenv
CASset=min
MALLOC_len=1
autoload=no
baudrate=115200

~~~
 簡単。

【邪道な方法】
アドレス情報がわからなかったり、ソフトをインストールできないデバイスを持っている人もいると思う。そういう場合でも、読むだけならできる。
 
1. mtdデバイスを探し出す
$ ls  /dev/mtd*
/dev/mtd0    /dev/mtd1    /dev/mtd2    /dev/mtdblock0  /dev/mtdblock2
/dev/mtd0ro  /dev/mtd1ro  /dev/mtd2ro  /dev/mtdblock1
 mtd0~mtd2があるようなので、mtd0でチャレンジ。

2. mtdデバイスの中身を吸い出す
$ dd if=/dev/mtd0 of=~/mtd0.bin

3. odで開始アドレスと終了アドレスを探し出す
$ od -Ax -c mtd0.bin | less
これで、「c   o   n   s」など、環境変数に設定されていそうな値を適当に入力して、値が入っている場所を探し出す。


終わりは\0が続いているだけなので簡単。

4. \0区切りで分割する
見ての通り、\0で区切られてASCII文字が格納されているだけなので、開始アドレス~終了アドレスのデータを取り出して、\0で分割して出力してあげれば終わり。
$ ruby -e 'ARGF.seek(0xa0004); buf=ARGF.read(0xc0000-0xa0004); puts buf.split(/\0/)' mtd0.bin
CASset=min
MALLOC_len=1
autoload=no
baudrate=115200
bootargs=console=ttyS

 ~~~

CRCがあるようなので、間違っても書こうとはしないこと。