海外の交通規則たち
僕は海外でレンタカーを借りたことがある。アメリカで一週間、フランスで一ヶ月くらい運転した。さて、日本人が国外で運転するにはどうしたらいいでしょう?
答えは簡単、国際免許証を貰えばいい。もちろん現地でもう一度運転免許を取り直せばいいんだけど、海外留学・転勤でも無い限りそんな手間は掛けたくない。そんな人のために大体の国では国際免許証というのを持っていけば*1合法的に運転できることになっている。*2
僕が最初に海外で運転したのはヨーロッパだった。国外免許証が必要というのをみて、早速免許センターに足を運んだ。必要書類は普通の免許証、パスポート、そして写真一枚。一体どんな講習があるのだろうとドキドキしながら手数料を払い、待つこと十分。そしてあっさりと渡される国際免許証を前に固まってしまった。あれ、全く交通規則とかを教わらなくていいの…
そう、不親切なことに交通規則を何ら教えてもらえない。考えてみれば免許センターの人が百近い外国の交通規則を個別に案内してくれるはずもないんだけど、アメリカと西欧くらい教えてくれてもいい気がする。ググれば出てくるんだけど、毎回調べるのも手間なのでまとめておきたい。
アメリカ (USA)
言わずもがな右側通行。大体の国は右側通行なので日本人には厳しい。僕はいつも右折の時に「左折左折左折…」左折の時に「右折右折右折…」と心に念じつつ鏡写しに行動することでうっかり対向車を見ないで左折したり右折して反対車線に飛び込んだりしないようにしている。
アメリカの不思議なことといえば未だにヤードポンド法を使っていること。何が困るって、車のメーターも速度制限も全部mph(マイル毎時)になってることだ。なのでメーターをkm/hだと思って運転すると大変なことになる。僕が運転したのはベイエリアだったので周りに合わせとけば済んだから余り考えなかったけど…ちなみに最高速度自体は州ごとに全然違ったりするらしい(Speed limits in the United States - Wikipedia)。だいたい日本の実勢速度と同じと思って大丈夫。
まだまだ不思議なことがある。「赤信号でも右折していい」のだ。僕はこれを知らなくて、赤信号で右折待ちしていると後ろの車からクラクションを鳴らされていた。せっかちな車もいるんだなぁと思ってたんだけど、僕のほうが間抜けだったということになる。注意してほしい。
あと、マイナーな点として高速道路の舗装が異様に悪いのでぜひ安全運転に気をつけたいところ。
西欧
西欧の国は高速道路も下道もさらっと国同士でつながっている。他の国に入るときには*3みたいな標識があって交通規則が変わるらしいことはわかるんだけど、もちろんそんなのまじまじと見られないわけでちゃんと調べておくべき。
まずヨーロッパの国で不思議なのは最高速度だ。高速道路の最高速度が130km/hの国が多く、日本(の建前)よりもだいぶ速いけど実際の速度で言ったら少し速いくらいかもしれない。不思議なのは下道の最高速度で、片道一車線の普通の下道でも、フランス90km/h、ドイツ・オーストリアに至っては100km/hの最高速度で、そして実際にみんなこの速度で走っている。ただ、街の中は50km/h規制が敷かれていて、街の名前が書いてある看板を見たら絶対に速度を下げないといけない。このへんに日本の下道が遅い理由がある気がしていて、日本の下道というのはバイパスを除くと大体ほとんど街の中か急峻な山の中でどっちにしても速度を出す余地なんて無いのかもしれない。
制限速度といえばドイツのアウトバーンの最高速度が無制限というのは有名な話で、実際にとんでもない速度で追い越し車線をかっ飛んでいく車もよく見る。しかし、ドイツ人気質なのか工事規制などで50km/hなどがかかっていると全員がちゃんとその速度制限を守って走っている。日本の高速道路であの手の制限を守って走っているケースはほぼ見ないけど、ドイツに行ったら注意して守ってほしい。
ラウンドアバウトも西欧の運転では避けて通れない。田舎の幹線道路の交差点はほぼ全て環状内優先のラウンドアバウトで大変だけどなれるとそれなりに楽です。典型的には四方向のもの、つまり普通の十字交差点と等価なものが多い。
一方、パリ市内ではコイツはあまり見かけない。でもその代わりパリ市内のラウンドアバウトは「右方優先」=「流入車優先」のものが多く、回っていてもお構いなしにどんどん割り込まれて*4ちっとも出たい方向に出られない。そのボス中のボスが有名なエトワール凱旋門の交差点で、そもそも道の方向が12方向あり、真ん中の車は常に三重くらいに渦巻いている。そして右から来た車にどんどん押しやられて真ん中に詰め込まれて、くるくる回るものだから出口の方向がわからなくなる。出たい方向から一本ずれた方向に出てしまうことは当たり前と思ってリカバリに努めよう。そもそも迂回するというのもいい考えだ。
今度ヨーロッパに旅行に行くのでその時までには最高速度あんちょこメモをつくろうと思います、それでは。
*1:普段の免許証も同時に所持していないとダメなので注意されたい。
*2:国際免許証はジュネーブ条約というものを根拠にしているそうで、国外運転免許証が有効な国(ジュネーブ条約加盟国) 警視庁を見ると例えばドイツみたいに加盟していないメジャーな国もある。ただし、在ドイツ日本国大使館 - 領事情報 : ドイツでの運転・運転免許証切り替え関するインフォメーションのように二国間の取り決めで国際免許証で運転できてしまうことが多い。
*3:File:France road sign C25a.svg - Wikipediaから引用
*4:概してフランス人の運転はドイツ人と比べて雑で荒い。
Haskell PlatformをUbuntu 13.04に導入する
あらまし
本来Ubuntuでは最新にこだわりさえしなければ
sudo apt-get install haskell-platform
で済むのだが、今回13.04 raringを今日2013年6月1日に導入するという事態に関して言うと最大限面倒。
- Haskell Platformは現在のバージョンが2013.2なのだが、13.04リリース時はひとつ前のものでghc 7.6に対応していなかった。にもかかわらずUbuntuはghc 7.4ではなくghc 7.6をパッケージとして採用したためにHaskell Platformが収録されないというふざけた事態に。
- しかもその肝心のghc 7.6は7.6.2で、haskell platformの導入要件である7.6.3を満たしていなかった。ghcから入れる必要がある。
- ghcのバイナリパッケージはgmp10じゃなくてgmp3に依存するので使えない。
要はどっちもソースから入れないといけないわけですね。bootstrapのGHCあるだけマシか…
つべこべ言ってないでGHCをビルドする
まずは下ごしらえをしよう
# 依存ライブラリを事前に導入, ghcもbootstrapに必要なので導入 sudo apt-get install devscripts equivs build-essentials ghc # これでghc依存のライブラリをまとめたdebができる mk-build-deps ghc # これをインストールすればいいんだけど、dpkgは依存の解析をしないのでコケる sudo dpkg -i ghc-build-deps_7.6.2-1ubuntu1_amd64.deb # で、apt-getで修復をかけると依存するライブラリが全部ごっそり入る sudo apt-get install -f
ではいよいよビルドだ。
tar xf ghc-7.6.3-src.tar.bz2 cd ghc-7.6.3 ./configure --prefix=/usr/local/opt/ghc-7.6.3 make sudo make install
今思えば/usr/localに直接放り込んだほうが早かったが、後の祭りである。
Haskell Platformの導入
# 何故かは知らないがOpenGLが必要らしい sudo apt-get install freeglut3-dev ./configure --with-ghc=/usr/local/opt/ghc-7.6.3/bin/ghc --with-ghc-pkg=/usr/local/opt/ghc-7.6.3/bin/ghc-pkg --with-hsc2hs=/usr/local/opt/ghc-7.6.3/bin/hsc2hs make sudo make install
シンボリックリンク
なぜかGHCを変なところに入れてしまったのでリンクを貼っておく。
for i in /usr/local/opt/ghc-7.6.3/bin/*; do sudo ln -s $i /usr/local/bin/`basename $i` done
hsenv導入
依存関係の衝突が一番怖いので、とりあえずhsenvを入れておいて、アプリケーションごとに違う環境を使おう
cabal install hsenv
Use persistent iptables on Debian
Now I cannot input any Japanese characters on my f**kin' arch laptop, so I write this article in English.
How should I make iptables persistent?
RedHat-like distro has /etc/sysconfig/iptables for persistent iptables, while Debian does not. How should we do? We used to write /etc/network/if-pre-up.d/iptables & /etc/network/if-post-down.d/iptables by hands. Now the answer is clearly shown in iptables - Debian Wiki. Let's install iptables-persistent.
sudo apt-get install iptables-persistent
This command tells you two important informations.
- The rule files are located in /etc/iptables directory. rules.v4 is for IPv4, while rules.v6 is for IPv6.
- At this time you can import your iptables config automatically, however, you have to manually save rules from now on.
iptables-save > /etc/iptables/rules.v4 ip6tables-save > /etc/iptables/rules.v6
Those commands will help you.
Gitのrebaseを楽に済ませよう
topicブランチをrebaseしてmasterに放り込みたい時がある。真面目にはgit merge --squashとかでいいんだろうけど、以下の様なフローを取りたいことがある。
git checkout topic # on topic branch git rebase master # ... git checkout master git merge topic # fast forward!
これをサボりたい。ちなみに答えはわかってない。
autojumpはaptで入る
autojumpはaptでいれるのが楽(終わり)ただし、/usr/share/autojump/autojump.zshをsourceすること。これだけでうまく行く。
システムのパーミッションを大幅に狂わせてしまった時
事故が起こるのは常に一瞬であり、一方平穏を取りもどすのはとても難しい
後輩が公開Subversionリポジトリを研究室のサーバに作っていたが、聞けば/root/SVNに作ったという。いやいや、/rootは700でしょうと俺は諭して議論の結果/var/svnとかが適切だけども容量の関係で他の場所に移動することになった。さて、問題は/rootのパーミッションを元に戻さねばならない。簡単、朝飯前である。
/root# chmod -R go-rwx * ls -la /root
いかん、隠しファイルどもが残ってしまった。やり直し、やり直し。
/root# chmod -R go-rwx .*
これにて一件落着…にしては終わるのが遅すぎる。そして、permission deniedとか言っている。いや、そんなややこしい話じゃないんじゃ?そして、そのログを見てみると/proc/なんちゃらとか書いてあった。
修復が簡単そうに見えたとしても実際の手間はその何倍にもなる
うわー、やってもたわー、と言う感じである。つまり、.*と書いてしまうと、..が入ってしまってルートから全部chmodしてしまうことになったわけである。ちなみにもしZshを使っていたら.*と入力したところで<Tab>を入力するとグロブパターンがその場で展開されるのでこういう時も「あれ、..が入っている」とか気付けるので安心である。rootでZshとか見たことないけどな。なにはともあれ急いでC-cで止めて現状確認を行う。
#ls -l / 合計 84 drwx------ 2 root root 4096 2012-xx-xx 11:47 bin/ drwx------ 4 root root 4096 2012-xx-xx 19:00 boot/ drwxr-xr-x 18 root root 3340 2013-xx-xx 17:52 dev/ drwxr-xr-x 92 root root 4096 2013-xx-xx 18:06 etc/ drwx------ 22 root root 4096 2012-xx-xx 11:03 home/ lrwxrwxrwx 1 root root 30 2012-xx-xx 16:50 initrd.img -> boot/initrd.img-2.6.32-5-amd64 drwx------ 11 root root 12288 2012-xx-xx 18:59 lib/ lrwxrwxrwx 1 root root 4 2012-xx-xx 16:41 lib64 -> /lib/ drwx------ 2 root root 16384 2012-xx-xx 16:39 lost+found/ drwx------ 3 root root 4096 2012-xx-xx 16:40 media/ drwx------ 3 root root 4096 2012-xx-xx 16:34 mnt/ drwx------ 4 root root 4096 2013-xx-xx 17:16 opt/ dr-x------ 139 root root 0 2013-xx-xx 17:51 proc/ drwx------ 7 root root 4096 2013-xx-xx 18:20 root/ drwx------ 2 root root 4096 2012-xx-xx 19:00 sbin/ drwx------ 2 root root 4096 2010-xx-xx 15:30 selinux/ drwxr-xr-x 2 root root 4096 2012-xx-xx 16:41 srv/ drwxr-xr-x 13 root root 0 2013-xx-xx 17:51 sys/ drwxrwxrwt 5 root root 4096 2013-xx-xx 19:20 tmp/ drwx------ 10 root root 4096 2012-xx-xx 16:41 usr/ drwxr-xr-x 16 root root 4096 2012-xx-xx 15:52 var/ lrwxrwxrwx 1 root root 27 2012-xx-xx 16:50 vmlinuz -> boot/vmlinuz-2.6.32-5-amd64
清々しいまでに700になっている。ただし、いくつか幸いなことがあった。
- chmod 700とかではなくgoからrwxを消しただけなのでsuid,gid,stickyという一番厄介でイレギュラーなビットは全て保存されている。*1
- これまた厄介な/etcと/varは手付かずだった。*2
というわけでまずは二次災害を防ぐために深呼吸三回してから作業にとりかかる。具体的には簡単なディレクトリでは次のようにして済ませた。
find /opt/hoge/ -perm u=rw -exec chmod go+r {} + find /opt/hoge/ -perm u=rwx -exec chmod go+rx {} +
大体のファイルは644か755になっている訳で、だいたいこれでうまく行く。ただし、
- 一部のファイルでは600や700が要求されることがある。
- suid,sgid,stickyが付いていると-permの条件を満たさないのでこれで変更されない。
ことには留意されたい。なんにせよ、単純な場所以外でこういうことをして傷口を広げるのはおすすめできないので一度-printして自分のマシンと見比べるなどするのがいい。
/proc以下に関しては所詮カーネルの見せる幻影であり、真面目に直してもむなしいだけなのでこれは再起動一発で直すことにする。で、再起動した後あっさり終わることを祈りつつ以下を試した。
xe@localmachine$ ssh hogeserver Permission denied (publickey).
…何かpermissionを直し忘れているだろうか?
root@hogeserver# ssh localhost Permission denied (publickey).
鍵のパーミッションなどを確認しても問題はないはず。SSH固有の問題を疑い、とりあえずローカルで調べることにする。とはいえサーバ機なので自分のパスワードはなく、suしてみることにする。
root@hogeserver# su - xe cd: can't cd to /home/xe
いや、そんなはずは…/home/xeに行けないのが駄目ならcdしなければいいじゃない。
root@hogeserver# su xe Cannot execute /bin/bash: Permission denied
完全に詰みました。
盲点は気づかないから盲点と呼ばれる
このあとdpkg -L openssh-serverの結果のパーミッションを全部確認してみたり、strace su xeしてみたり涙ぐましい努力をしてみたのですが、駄目。
で、rootでログインできなくなったらどうしよう…と思いつつもエイヤで再起動、rootログインはできるものの上の3つは相変わらず駄目。そして、このまま格闘しても全く分かる気がしなかったので藁にもすがる思いで"Cannot execute /bin/bash: Permission denied"をググることにした。そして、Cannot execute /bin/bash: Permission denied | 作業日報を開いた私は驚愕の事実を目の当たりにするのであった。
そう、 / のパーミッションが間違っているのである。いやー、これは盲点だわー、ls -l --color /してたけど/は見えないもんなー。という事でこれを直したら無事に全てが動いた。
HDDの物理障害から立ち直る
HDDがある日突然ファイルが読めなくなった。言われてみれば予兆はあった。Picasaでファイルを開くと奇妙に遅いとかである。しかし、USB接続していたのでS.M.A.R.T.も読んでなかったし、音もちゃんと聞いていなかった。なによりバックアップを取っていなかった。そういう状況で、突然ファイルは見えなくなった。なので、とにかくぶっ壊れたディスクから中身を吸いださねばならない。
以下の内容は作者の個人的体験を記述したものです。またコマンドはあなたのPCのデータを破壊する可能性があります。コマンド例を信用せずよく自身で調べ自身の責任のもとで実行してください。
修復業者
HDDの修復業者はあっちこっちで広告を出しているものの、結局のところオントラックというところに頼むのがいいという事は分かった。ただ、オントラックはハイクオリティ・ハイペイメントである。個人相手には「ディスカウント」しているが、それでも20万円という額が必要になる。ここでこれに飛びつく気にはなれなかった。
無料で修復 - Windows
じゃあ、という事で当然思いつくのがddなんだけど、まずはWindowsでNTFSを話してサルベージすることにした。Windows上でアッチコッチのフォルダに行って
xcopy /s/e/c/f/h/j SRC DST
とやって'n'を連打した。後のほうではnnnnnnnnのようにnを続けて入力した物を改行の後に続けてコピペすることで標準入力に流せることが分かり少しは作業がはかどった。これで大半のデータをコピーすることには成功した。しかしなにぶん完全に取り切った感じがしない。
無料で修復 - dd
次に考えるのは当然ddである。ddとはUnixに存在する「ブロックデバイスをとにかく前からコピーする」ツールである。
dd if=/dev/sdX of=/path/to/image bs=4096 conv=noerror,sync count=XXXX
こういう時は一回の読み書きサイズをHDD自体のセクタサイズの512バイトに合わせてbs=512にするのが定石である。さもないと、例えばbs=4096とした時に4096バイト中の512バイトが1箇所エラーになっただけで周りのセクタもエラー扱いにされてしまうからだ。しかし、これを実行しても全く終わる気配がない。最初100GB少しまでは順調に進んだが、途中から0.5kB/sというHDDが動作しているかすら疑わしい速度まで落ちてしまった。この原因を考えるに、ddは前から順番にreadシステムコールを発行してファイルを読もうとする。つまり、badな領域を読む際に大きな時間がかかると、次のデータ領域を先読みすることもなくただただ時間がかかることになってしまう。こういうオーバーヘッドをシーケンシャルに蒙るのはバカのすることで、本当は並列にI/Oを発行して同時に複数のreadを待てば相当な高速化が図れるはずである。
無料で修復 - GNU ddrescue ←イマココ!
そこで頭のいいツールを(今更ながら)ググった結果あっけなく見つかった。Ddrescue - GNU Project - Free Software Foundation (FSF)である。GNU ddrescueであって、dd_rescueとは別物なのには気をつけたい。どれくらい頭のいいツールかを見てみよう。
GNU ddrescue はまずデータの良好な部分を先に復旧し、不良だったり読み込みが遅かったりする領域を後回しにして、復旧を効率よく進行させます。こうすると故障したドライブから最終的に復旧できるデータの量を最大化することができます。
標準の dd ユーティリティも故障したドライブからデータを保存するのに使うことは可能ですが、データを前から順番に読んでいくのでエラー領域がドライブの前の方にあった場合データを救出する先にドライブを駄目にしてしまいます。
他にエラーが見つかったときは小さめのサイズで読み込み直すようなプログラムもありますが、結局前からデータを読むことには変わりありません。前からエラー領域を延々と読むことはただ時間がもったいないだけでなく、データの読み込みをする前にディスクの表面やヘッドなどドライブの機構にダメージを与えてしまう事になります。結局、残っている良好なデータを救出できる可能性を自分でなくしてしまうわけです。
ddrescue のアルゴリズムは以下のとおりです。ちなみに、ユーザーは処理をいつでも中断することができますが、不良なドライブを読み込んでいるときはカーネルが読み込みを断念するまで長時間ブロックすることがあります。
- オプションでログファイルから以前の実行状態を読み込みます。ログファイルがなかったり空だったりする場合は全域が non-tried だとして扱います。
- 入力ファイルのうち全ての non-tried の部分を読み込み、そのうち失敗したブロックをnon-trimmedとしてマークして読み飛ばします。non-tried の部分だけが大きなブロックサイズで読まれます。
Rescue domain
Block or set of blocks to be acted upon (rescued, listed, etc). You can define it with the options `--input-position', `--max-size' and `--domain-logfile'. The rescue domain defaults to the whole input file or logfile. その他の trimming, splitting や retrying はセクタ単位で行います。各セクタを最大2回は読みこもうとします。最初は大きなブロックサイズで読み込もうとし、次は1セクタごとに読み込もうとします。GNU ddrescue Manual
- non-trimmed ブロックを後ろから1セクタ毎に不良セクタが見つかるまで読み込みます。途中で不良セクタが見つかれば bad-sector とマークし、残りのブロックを non-split とマークします。
- non-split ブロックを1セクタ毎に前から読み込み、不良セクタがあれば bad-sector とマークします。ブロック内にある程度多くの不良セクタが見つかれば、そのブロックを半々に分けて後半のブロックを読み込みます。再帰的にこれを続ければログファイルが長くなりすぎることなく大きな non-split ブロックを分割していくことができます。
- オプションで不良セクタを指定されたリトライ数に達するまで読み込み直します。
- オプションで今後の実行のためにログファイルを書き出します。
よく読むと決して並列I/Oするとは言っていなかった。とはいえとっとと読めるところを読むというのはうれしい限りだ。ではUbuntuでインストールしよう。
$ sudo apt-get install gddrescue
実に簡単である。しかし問題があって、これまでddで一ヶ月近くコピーしてきた部分が既に存在することである。ただ、幸いGNU ddrescueは「今どこまでなにをしたか」と言う状態を簡単なテキストファイルとして保存するようだ。そのため、適当に実行してみると簡単に「既にNバイトコピーし終わった」状態を再現できた。
$ sudo ddrescue /dev/sdX /tmp/hoge rescue.log ...# C-cで止める $ cat rescue.log # Rescue Logfile. Created by GNU ddrescue version 1.16 # Command line: ddrescue /dev/sdb /tmp/hoo.img rescue.log # current_pos current_status 0x02490000 ? # pos size status 0x00000000 0x02490000 + 0x02490000 0x76DF0000 ?
どうやら0x02490000までがコピー済み、0x76DF0000が総サイズ残りのサイズである。詳しくはGNU ddrescue Manualを参考にしてほしい。ちなみに、statusの意味は以下の通り。
GNU ddrescue Manual
文字 意味 '?' non-tried ブロック '*' non-trimmed ブロック '/' non-split ブロック '-' bad-sector ブロック '+' コピー済みのブロック
いよいよ後はこのrescue.logのサイズを修正して走らせるだけである。
$ vim rescue.log # 編集 $ sudo ddrescue /dev/sdX /path/to/image rescue.log
ちなみにGNU ddrescueはCtrl-cで中断し、また後で同じログファイルを指定して実行することでresumeすることが出来る。つくづくありがたい。
実行中に分かったこと
- ddrescueの実行フェーズのうち、tryとtrimは1セクタでもポシャったらやめてしまうので一番時間がかかるのはsplitということになる。で、そのsplitなんだけどなるべくサイズの大きなブロックからやり直してほしいものである。例えば100KBの領域とかだとこのボロボロのディスクだとまるっと読み込めないこともあり得るのに対して、サイズの大きなブロックは端っこだけ駄目なところがあったという可能性も大いにある。そこで、一度trimフェーズまで終了した時点でCtrl-cで終了し、「これはやり直してほしい」と思うブロックのstatusを'/'から'?'に書き直してしまう。これでもう一度実行すればそのブロックを先にコピーしてくれるというわけだ。
- -a/--min-read-rateというのを指定すると最低これだけの速度が出ていないと後回しになるというオプションなのだけど、Ubuntu 12.04にはバージョン1.14が入っていてこれにはこのオプションがなかった。Ubuntu 12.10ならあるみたい。rescueに1年とかかかるわけにも行かないから本当のところこれを付けたいんだけど。
即興でThis script visualize the logfile of GNU ddrescue. · GitHubというddrescueのログファイルから進行状況のグラフを書くスクリプトを組んだ。だが、ラスタ画像なので最小でも1pxの幅を持たせないと読めないわけで、実質的にほとんど大きさに意味がないというか…大きいブロックは確実にでかいブロックだけど、小さいブロックはある程度以下は全部一緒くたっていう。まあ、512Bを500GBの中で考えるのが無茶というもの。
そしてエントリを書いてから一週間、コピーは遅々として完了しません。途中で次のようなものができました。
- https://gist.github.com/4645399はnonzeroなセクタだけddするプログラムです。何がしたかったかというとマウントし忘れた状態でddrescueしてしまったので、元のディスクイメージと新しいディスクイメージをマージしたかった感じです。
- https://gist.github.com/4652937は全く同じ内容の画像をハードリンクで処理するものです。今画像のフォーマットが違う時にヤバいんじゃとか思いつきましたが面倒なので放置します。
まだコピーは終わっていないが幾つかの知見を得た。
- -dオプションはdirect I/Oなので付けるといいとか。本当かはしりません。
- -r 3で3回リトライとか出来る。そしてリトライすると思ったより読める読める!最後の切り札である。