Mac上でMiddlemanを使ってCentOSにホストするとNFD問題にぶち当たる

やぎすけAdventCalendar2016

Posted on Dec 17


こんにちは、やぎにいです。

やぎすけ Advent Calendar 2016の17日目です。
残すところあと1週間程となってしまいました。

昨日はうなすけががやぎすけ Advent Calendar 16日目 testの追加)を書いてくれました。

今日はこのブログをジェネレートしているツール、Middlemanの話です。


経緯

このブログサイトや、yagi2.comMiddlemanを使って作成しています。
ブログを構築する手順についてはこのブログでもMiddlemanを使ってさくっとブログを立ち上げるぞい!として書きました。

実際僕はこの手順を踏み、Middlemanを使って私物のMacbookProにて記事を書き、そのままMBP上で$ bundle exec middleman buildを行い、出来た成果物であるbuild/を契約しているVP(CentOS)Sへアップして記事を更新していました。 すると、つい最近とある問題にぶち当たりました。

問題に当たったのは今月1日に、このアドベントカレンダーの1日目の記事やぎすけ Advent Calendar 2016を書いてCentOSのVPS上にファイルをアップし、更新したときのことです。
タグに「やぎすけAdventCalendar2016」というのをつけているわけですが、もちろん同じタグの記事をリスト閲覧できるようにArticles tagged 'やぎすけAdventCalendar2016'というページがMiddlemanではタグを解釈して自動的に作ってくれます。
この時このページのHTMLファイルの名前は「やぎすけAdventCalendar2016.html」になり、書くファイルからリンクされる形になります。

本来は。

本来は、そうリンクされるはずなのですが、実際にはなぜか404エラーが出てしまうのです。
しかし、手元のMacのlocalhostで動かすときは正常にリンクが働く……。
しばらく頭を抱えることとなりました。


NFD問題

  • やぎすけadventcalendar2016.html
  • やぎすけadventcalendar2016.html

みなさんは上記2つの違いがわかるでしょうか。
実は「ぎ」が違うのです(多分変換してるので実際には違いは消えている)。
それぞれURLエンコードをした際に

  • %E3%82%84%E3%81%8E%E3%81%99%E3%81%91adventcalendar2016.html
  • %E3%82%84%E3%81%8D%E3%82%99%E3%81%99%E3%81%91adventcalendar2016.html

になってしまったのです。
判明したのは、VPSにsshで潜って原因を探っている時。
「やぎすけAdventCalendar2016.html」というファイルが有るわけですから、$ cat やぎまで入力しTabキーを推せば本来の補完昨日では$ cat やぎすけAdventCalendar2016.htmlと自動で保管されるはずです。
しかし、保管されなかったのです。

  • $ cat や Tab → 補完される
  • $ cat やぎ Tab → 補完されない

という状態でした。
あれ……「ぎ」がおかしい……?
何が何なのか全然わからない僕は頑張って調べ「NFD問題」というのが存在するということがわかりました。
詳しくはWikipedia - Unicode正規化にすべて書いてあるのですが、NFCとNDFの2つを取り出して説明すると。

  • NFC : 1文字は1文字 ぎ (きに濁点がある)だろうが、1文字なんだよこれは という形式
  • NFD : 濁点半濁点などを本来の文字とは分離してエンコードする ぎ は き + ゛

これを採用している違いはファイルシステムにあり、OS X の HFS+は後者のNFDしています。
つまり
ファイルシステムの問題(くそ!)

Macですべて完結させる場合はNFDで全然問題がないのですが、今回はそのMacで作ったファイルをCentOSでホストしているために、NFDになっているファイル名を解決できずに404エラーが出ていたということです。


こうした

実は今まで、scpコマンドを使用してVPS上にファイルを送っていたのですが、どうやら調べてみるとscpはNFC,NFDについて全くノータッチ。(だから問題が起きたわけですが)
最新版のrsyncであれば--iconvオプションが使えるようになるので処理できるようになります。なるほど。
じゃあHomebrewで入れよう

1
2
3
4
$ brew tap homebrew/dupes
$ brew install rsync
$ rsync --version
rsync  version 3.1.2  protocol version 31

バージョンが3.1とかそれになっていればOK。

1
$ rsync --iconv=UTF8-MAC,UTF-8 やぎにい.html example.com:/

とかしてあげると自動的に処理してくれる--iconv=UTF8-MAC,UTF-8が大事な部分です。


これから

まさか「やぎにい」でこの問題にぶち当たるとは思っていなかったのですが、実際ぶち当たるまでこのUnicode正規化についてまったく知りませんでした……。
そしていまはまだ$ bundle exec middleman buildしたあとに$ rsync ...としてVPS上にファイルを上げているわけですが、いい加減やめたいです。

今はとりあえずGitHubにブログのソースをPushしているわけですから、masterブランチにコミットが発生した場合にCIを使用して自動でビルド〜デプロイするようにしてあげたいと思います。
それが出来たらまた、手順等このブログで紹介します。

気をつけなはれや!

以上、やぎにいでした。



comments powered by Disqus

<< RaspberryPiを使って、家に超A&G+を垂れ流す環境を作った     GitHubレポジトリにMavenのリポジトリを作成する >>



2016 やぎ小屋