watermint.org - Takayuki Okazaki's note

デジタルファイリング - データの整理整頓

気がつけばあっというまに2016年の大晦日。昨年の大晦日も大掃除をしたり、ファイルの整理をしたりと今年は整理整頓の一年でした。

断捨離をしつつ部屋の掃除も一段落しましたが、今年はデジタルデータの整理にも時間をかけています。デジタルデータで特に時間をかけたのが写真の整理です。昨年末から約1年かけて紙などアナログデータと、デジタルデータの整理を続けてきました。10万枚を超える写真データの整理とストレージ選びでもご紹介した通りNASを廃してクラウドストレージに移行しました。

この1年試行錯誤をして、整理整頓でこだわるべきだと感じたのは次の2点でした。

  • なるべく長期保存に耐えるフォーマットに統一する
  • なるべく階層を減らし、フラットな構造にする

それぞれどのようにこだわったのか紹介していきます。

長期保存に耐えるフォーマットへの統一

手元に残るうち、自分で作成した一番古いファイルのタイムスタンプを見ると1995年10月31日となっています。当時高校生でしたが、かれこれ20年以上経っています。ほとんどのファイルはまだ変換作業などすれば利用可能ですが、変換せずに閲覧できればファイルの利用価値はぐっと上がります。

あまり古いドキュメントをいまさら変換するのは面倒ですし特にモチベーションもないのですが、最近つくったドキュメント類はPDF/XまたはPDF/Aで保存し、フォントや埋め込み画像なども含めた格好で保存するようにしています。

ドキュメント類は上述のようにPDF/Aなどで保存していれば間違いないのですが、少し面倒なのが動画ファイルです。デジカメで撮った動画ファイルが手元にはたくさんありますが、デジカメの機種によってファイル形式はばらばらです。これらは一括で、H.264のようなに今どきの機器でプレビューしやすいフォーマットに変換しました。

紙からデジタルデータに

紙のデータは10年程度前から積極的にデジタルデータ化しています。クレジットカードの申込書や明細、商品を買ったときに同封されていた注意書きの紙、携帯電話やインターネットサービスの申込書や規約、購入した家電の説明書など。

同等のデジタルデータがダウンロードできる場合には、ダウンロードして保存しておき、そうでない場合にはスキャナーをつかってPDFデータにしておきます。

紙媒体ではサイズがまちまちだったり、大きさや重さの制約があり一ヶ所に保存するのは難しいですがデジタルデータにしてしまえばフォーマットを統一して参照することができます。

紙媒体では契約書など現物が必要なものもありますが、デジタルデータにしておくことで、契約年月日を知りたいとか、契約の種類が何だったかといった確認のためには重宝します。

なるべく階層を減らし、フラットな構造にする

本屋に行くと「整理整頓」「片づけ上手」といったキーワードの本がたくさん見つかります。また、最近では「ミニマル」とか「断捨離」といったキーワードのように捨てることについて注目して説明している記事も多く見られます。

デジタルファイリングもおそらくこの手法をそのまま採用できるだろうというのが最近の考えです。

片づけ指南本によると基本的な考えは「よく使うものは手前に置く」というシンプルなルールであると指南されています。デジタルデータでもこれは同様です。ただ単純にフォルダ構成を考えればいいというわけではなく、仕事の進め方も同時に変えていく必要があります。

最近のファイル

よく使うファイルというのはほとんどん場合最近つくったファイルです。

最近書いている記事のファイル、最近とった写真、進行中のプロジェクトといったファイルが最小の手数で開ける位置にあれば作業効率はバカにならないほど改善します。

ですから、Macならばファインダー、Windowsならばエクスプローラーを開いてすぐにこれらのファイルやフォルダにたどり着くことができるようにします。

こういったファイルやフォルダをデスクトップに置いている人も多いでしょう。デスクトップの使い方については少しこだわりがあるのでこちらも紹介させていただきます。

デスクトップの整理

個人的にはデスクトップは一時的な作業領域ととらえていて、一日の終わりに完全に空っぽの状態にしています。数年前受講したメール整理法の研修を受けました。この研修では「Inboxを毎日空っぽの状態にしましょう」という整理術を紹介していました。

このメール整理術ではフォルダに割り振るか、TODOリストに加えるか、スケジュール帳に書き込むか、削除/アーカイブするか行き先はこの4つだけ。この狙いは、まぜこぜになった情報一覧から必要な情報を探すのにいちいち時間がかかってしまう時間ロスを減らすことにあります。

デスクトップを空っぽにするのも同じ狙いです。たとえばプレゼンテーションスライドを作るときに大量の画像素材を準備するときは、デスクトップへ乱雑に置いていきます。ある程度情報を整理してプレゼンテーションスライドに配置が終わればスライドはプロジェクトのフォルダなどに整理しデスクトップは空っぽにします。

もし、画像を乱雑にデスクトップへ置いたまま、別のプロジェクトの作業をデスクトップ上で始めてしまうと、どのファイルがプレゼンテーション用のものだったか探すための時間ロスが生まれます。さらにデスクトップを空っぽにするにしても、どれが不要なファイルなのか簡単に区別がつかないのでまた時間ロスがうまれたり、「念のため」ということでそのまま放置してしまうことになりがちです。

最近つくったファイルの置き場所

比較的よく利用する最近つくったファイルはWebサイトデザインなどの際によくいわれる「3クリックルール」を想定して整頓するとよいでしょう。チーム作業などのために、共有フォルダの構成が決まっている場合はショートカットなどを活用します。

開くフォルダの設定

ファインダーであれば、ファインダーを開いた時に表示されるフォルダを設定できます。

すべてのファイルを一ヶ所に

ここまでは今までも似たような整理をしていたのですが、今年はNASや外付けハードディスクなどに保存していたすべてのファイルをDropboxに移行していったのでさらにファイリングを工夫しました。

これまでバックアップのために外付けハードディスクに保存したりNASに分散管理するなどしていましたが、Dropboxに移行したことで冗長性の確保ついてはすべてDropboxに依存することにしました。これによって、同じファイルを手元で複数管理する必要がなくなったので、バックアップ頻度などバックアップ漏れがないことを意識しなくてよくなりました。

整理を進めるに当たって、冗長管理をする必要がなくなったのは大きな進歩でした。すべてのファイルが一ヶ所にまとまっていますし、重複したファイルを持つ必要がなくなったので不要なファイルをどんどん削除することができました。ファイル数、フォルダ数が減ったことによってフォルダの見通しがよくなりました。検索も簡単です。

ファイル総量の制限

外付けハードディスクを利用していたときには要領あたりの単価が安いこともあって湯水のようにディスク領域を利用していました。いまはパソコンやDropboxの容量制限もありますが、主にファイル発見への時間ロスを考慮して総量制限をしています。

ファイルが多すぎると探すための時間を使ってしまいます。ご家庭でもDeep learningなどで自動的に分類されて必要なファイルが探せる時代になればいいのですが、まだそういった使い方は先になりそうですから、時間ロスを減らすにはある程度ファイル総量を制限していくほうが理にかなっていると考えています。

11月ごろにMacBook Proを買い替えて、内蔵SSDが1TBのモデルにしました。これはファイル総量はだいたい1TBぐらいだと時間ロスも防ぎつつ必要なファイルを保存していくためにちょうどいいのではないかなと考えたためです。

これまでにデジカメで撮った10万枚の写真総量ではおおよそ2TB強ありました。特にNikon D800で撮影したRAWファイルは1枚当たり50MB前後とかなりの容量でした。ただ、ほとんどの写真は連射写真で個別に再利用することがなかったので、思い切ってすべて削除し、2TB強のデータを170GB程度までに削減しました。

この制限によって、見返すことも簡単になりましたし、内蔵SSD上ですべて処理できるようになったので昔の写真を含めてすべてブラウズするといった操作もストレスなく快適になりました。

フラットに配置する

フォルダの見通しをさらによくするために、すべてのフォルダを3〜4クリック程度でたどり着けるように整理しました。フォルダ階層をなるべく減らしてソフトウエア等の制約で必要がない限り4階層までにおさえるようにしました。

iPhoneやiPadなどのスマートデバイスでもたくさんタップをするよりは縦スクロールをしていくほうが簡単です。近年のパソコンでもタッチパッドなどが使いやすくなりスクロールは非常に簡単です。ですから、ファイルがフラットに並んでいるほうが階層が深くなっているよりもより目的のファイルを簡単に探すことができます。

フォルダ階層

五十音順/アルファベット順/日付順などファイルの種類におうじて工夫します。3年前から購読している新聞はすべてPDFでダウンロードができますが、新聞であれば日付順に並んでいると一目瞭然です。あまりファイルが多すぎても探しづらいので月ぐらいでフォルダを作っています。

すべてのファイルをフラットに配置したことで、過去のファイルを参照することが日常的な作業になりました。NASや外付けハードディスクに保存していた時には、よほどの確信がなければできない作業だったのでこれは大きな変化です。

整理整頓とデジタルファイリング

デジタルファイリングを工夫したことで過去の情報を扱うことが簡単になりました。10年前の家計簿を見直したり、冷蔵庫の製氷機を掃除する方法を調べたり、飲み会の場で友人に3年前の旅行写真を見せたり、2年前の新聞を見直すなど一ヶ所にデジタルデータとして保存していなければなかなか面倒でした。

この十数年でインターネットで一般的な情報を探したり、現在進行中のニュースを知ることは安価でかんたんにできるようになりました。一方で、自分にかかわる過去の情報は自分自身で整理していないとインターネット以前と同様にかんたんには探すことができません。

今年はデジタルファイリングが一区切りついたので、来年はこれらの情報を活用する方法を研究していきます。

Go: 複数のReader/Writerに対する帯域幅制御

ネットワークやディスクへの読み書き処理の際、帯域幅制御をしたい場合があります。低優先度の処理などによって主となるビジネスロジックが阻害されないよう制御するといった目的や、一つのサーバ資源で複数のサービスを提供するときに一つのサービスが資源を消費しすぎないようにしたいといった目的があります。

Goでこのような処理を書きたいとき、ざっと調べてみたところgo-flowrateという実装が見つかりました。

func main() {
    f, _ := os.Open("data.dat")

    // 100バイト/秒の帯域幅制御付きのラッパーをつくる
    f2 := flowrate.NewReader(f, 100)

    // 実際の処理
    // ...
}

使い方もシンプルできっちり制御できるのでこれでいいのですが、制御できるのが一つのio.Readerまたはio.Writerのみに対してのみ可能で、複数のio.Readerio.Writerに対しては制御することができません。

並列処理が必要なプログラムを書いているとちょっとこれではそのまま使えそうにありません。もう少しほかの選択肢を探してもよいのですが、ちょうどいいGoのプログラミング課題ということで新しく実装してみることにしました。

出来上がり

まずはでき上がったライブラリを紹介します。bwlimitとしてGithub上に公開してあります。利用例は次のようなイメージです。

func main() {
    // 100バイト/秒に制限
    bwlimit := NewBwlimit(100, false)

    // 複数のReader
    f1, _ := os.Open("data1.dat")
    f2, _ := os.Open("data2.dat")

    // ラッパーを作成
    fr1 := bwlimit.Reader(f1)
    fr2 := bwlimit.Reader(f2)

    // 実際の処理
    // ...

    // すべてのReaderがClose()されるかEOFになるまで待機
    bwlimit.Wait()
}

まずは帯域幅制御を制御するオブジェクト(上図ではbwlimit)を作り、さらにそれぞれラッパーを作成します。NewBwlimitの第二引数は帯域幅制限しているときRead/Write処理を待たせるかどうかです。

あとはラッパーを普通のio.Readerとして扱うだけです。並列処理をしていて、すべてのReaderまたはWriterについて処理が完了したかどうか知りたくなったので待機するWait()もつくりました。

仕組み

キューを作る方法などいくつか実装方法を検討しましたが最終的にはかなりシンプルな構造になりました。トヨタ生産方式の本を思い出してヒントを得ました。

タクトタイムという一定時間のリズムを刻んで、各拍子のタイミングで利用可能な帯域を現在有効なReader/Writerで分割して利用するアイデアです。

たとえばタクトタイムを1秒間に10回に設定したとします。帯域幅設定を1000バイト/秒にした場合、タクトタイム1回あたりに利用可能な帯域幅は100バイトです。有効なReaderが2つであればこの100バイトをわけあって、50バイトずつの読み取りを許可する枠を設定します。実際に、Reader側が読み取るかどうかはわかりませんが、読み取り可能な上限を制御することでこのような流量制御を行っています。

流量制御と障害防止

あるタクトタイムのときに、読み取りが実際に発生せず50バイト分の枠がまるまるある状態で、次のタクトタイムになったとき読み取り可能枠を50 + 50バイト分にはしないようにしました。流量はこれによってすこし減ってしまいますが、意図しない障害を防ぐためです。

読み取り可能枠が溜まりにたまって一気に転送が行われてしまうと、他のサービスへ影響がでることはもちろん、場合によってはルーターなどのバッファサイズを超えるなどして障害が発生することも考えられます。

利用例

また別の記事として各予定ですが、Dropboxへのファイルアップローダーをいま作っています。このファイルアップローダーで並列してファイルのアップロードをする際に、帯域幅制御をつけたかったのがこのライブラリ作成のモチベーションです。

Disk image file (.dmg) from command line

I prefer .dmg instaed of zip for archiving project data, etc. .dmg is handy for refering files, modify contents without extract files to somewhere.

.dmg can usable as like USB drive. Disk Utility tool can create/update .dmg from folder with various options. Options are like encryption, readonly, compression, etc.

But if you have tens of folders to archive, it’s better to use command line tools.

Create encrypted .dmg file

hdiutil is command line version of Disk Utility app. This command can mount/unmount/create/update disk image files. Please see man hdiutil for more detail.

Below script is part of my workflow of archiving project files. I’m using encrypted .dmg for archive. The script require prepare password file under $HOME/.dmg-password. Please create and store password for .dmg without LF.

And update permission like chmod 600 $HOME/.dmg-password to prevent read from other users. This sequence using password and encryption. But it’s not strong enough, reason described below.

#!/bin/sh

if [ $# -lt 2 ]; then
  echo $0 SRC_DIR DEST_DIR
  exit 1
fi

SRC=$1
DST=$2
PWD="$HOME/.dmg-password"

if [ ! -e $PWD ]; then
  echo Disk Image password not found
  exit 2
fi

for t in "$SRC"/*; do
  if [ -d "$t" ]; then
    echo Creating: $t
    n=$(basename $t)
    cat $PWD |                \
      hdiutil create          \
        -srcfolder "$t"       \
        -fs HFS+              \
        -encryption AES-128   \
        -format UDBZ          \
        -stdinpass            \
        "$DST/$n.dmg"
  fi
done

Preset password for .dmg in Key Chain

It’s kind of pain in neck entering password for opening .dmg everytime. If you open .dmg from Finder.app, the password dialog refuse copy & paste operation.

Password dialog

There is option “remember password in my keychain”. Concept is similar to this.

The password for disk image is stored in keychain which identified by UUID of .dmg. The UUID is referable by command like below.

$ hdiutil isencrypted YOURDISKIMAGE.dmg

Now you can store password through security command.

$ security add-generic-password -a (UUID above) -D "disk image password" -s (YOUR DISK IMAGE).dmg -w (PASSWORD OF DISK IMAGE)

Unfortunatelly, there are no option like -stdinpass. So the password must be passed through command line argument. This mean optential leak through ps command or shell history.

By the way, I’m using below script for preset password to disk images.

#!/bin/sh

if [ $# -lt 1 ]; then
  echo $0 [dmg file]...
  exit 1
fi

PWD=$HOME/.dmg-password

for FILE in "$@"; do
  UUID=$(hdiutil isencrypted "$FILE" 2>&1 | grep uuid | awk '{print $2}')
  BASE=$(basename $FILE)

  echo File: $BASE
  echo UUID: $UUID

  security add-generic-password -a $UUID -D "disk image password" -s $BASE -w $(cat $PWD)
done

When opening .dmg from Finder, operating system ask authorisation of using password by diskimages-helper.

Confirmation dialog

You can skip this dialog by -A option of security command, but this option authorise for all applications. It’s better not use this -A option for better security.

ディスクイメージファイル(.dmg)をコマンドラインから

Macでたくさんのファイルをひとまとめにするのであればzipで圧縮するよりも、ディスクイメージファイルにしたほうが便利なこともあります。zipだと標準では中身を確認するのに毎回どこかに展開しないといけないですし、ファイルの内容を変更するのも面倒です。zip用のツールを使えばおそらくそれらも解決できると思いますが、個人的にはディスクイメージファイル(.dmg)を使うことの方が多いです。

ディスクイメージファイルは外付けディスクのようなイメージでマウントして使えます。macOSに標準添付されている「ディスクユーティリティー」ツールを使えばこのイメージファイルを簡単に作ることができます。読み取り専用、読み書き可能、暗号化、圧縮などオプションを選ぶこともできます。

終了したプロジェクトのファイル一式は.dmgファイルとしてまとめていますが、まとめたいプロジェクトファイルがたくさんあったり、ワークフローを自動化したいとなってくるとコマンドライン操作を覚えると便利です。

ディスクイメージファイルの作成

hdiutilコマンドを使うとディスクイメージファイルの作成や設定変更、ディスクイメージファイルのマウント、アンマウントなどさまざま操作可能です。詳しくはman hdiutilをご参照いただくとして手元での利用例をご紹介します。

フォルダ以下にあるサブフォルダをそれぞれ.dmgとして一括変換したい場合に使っているスクリプトです。それぞれ一応暗号化しておこうということで、暗号化用のパスワードを$HOME/.dmg-passwordというファイルにあらかじめ格納してあります。パスワードファイルには最後に改行が入らないようにつくっておいてください。

あとパーミッションも chmod 600 $HOME/.dmg-passwordなど他者から読み出せないようにしておきます。そうはいっても、後述しますが一連のプロセスはさほど安全性が高いわけではありませんので「添付ファイルはパスワードつきzipでパスワードは別メールですぐ送信!」とあまり変わらないセキュリティーレベルとお考えいただいていいかと思います。

#!/bin/sh

if [ $# -lt 2 ]; then
  echo $0 SRC_DIR DEST_DIR
  exit 1
fi

SRC=$1
DST=$2
PWD="$HOME/.dmg-password"

if [ ! -e $PWD ]; then
  echo Disk Image password not found
  exit 2
fi

for t in "$SRC"/*; do
  if [ -d "$t" ]; then
    echo Creating: $t
    n=$(basename $t)
    cat $PWD |                \
      hdiutil create          \
        -srcfolder "$t"       \
        -fs HFS+              \
        -encryption AES-128   \
        -format UDBZ          \
        -stdinpass            \
        "$DST/$n.dmg"
  fi
done

ディスクイメージファイルのパスワードをKeyChainにプリセットしておく

暗号化しておいたのはいいですが、作成したディスクイメージファイルを開く際にいちいちパスワードを入力するのは面倒です。Finderからダブルクリックしてマウントしようとしたときに聞かれるパスワードダイアログはコピー&ペーストを受け入れてくれないというのもさらに面倒さを増しています。

パスワードダイアログ

パスワードをキーチェインに記憶させるというオプションがありますが、あらかじめコマンドラインから記憶させておけばいいという発想です。

ディスクイメージファイルに対するパスワードは一般パスワードとして各ディスクイメージファイルのUUIDと対応して管理されています。このUUIDは

$ hdiutil isencrypted ディスクイメージファイル.dmg

というようにisencryptedオプションで知ることができます。キーチェインにパスワードを追加するには

$ security add-generic-password -a (上記のUUID) -D "disk image password" -s (ファイル名).dmg -w (パスワード)

というように実行すればよいでしょう。securityコマンドの大変残念な点はhdiutil-stdinpassのように標準入力からパスワードを受け取る手段がどうやらなさそうな点です。

コマンド引数として実行してしまうと、シェルの履歴に残ったり、psコマンドなどでパスワードが漏えいしてしまうケースがあります。このような点から上述のように「添付ファイルはパスワードつきzipでパスワードは別メールですぐ送信!」というセキュリティーレベルとたいして変わらないと思っています。

さて、上記を合わせて次のようなスクリプトにしてあります。

#!/bin/sh

if [ $# -lt 1 ]; then
  echo $0 [dmg file]...
  exit 1
fi

PWD=$HOME/.dmg-password

for FILE in "$@"; do
  UUID=$(hdiutil isencrypted "$FILE" 2>&1 | grep uuid | awk '{print $2}')
  BASE=$(basename $FILE)

  echo File: $BASE
  echo UUID: $UUID

  security add-generic-password -a $UUID -D "disk image password" -s $BASE -w $(cat $PWD)
done

このようにキーチェインにパスワードを設定したファイルを開こうとすると次のようにキーチェインからパスワードを取り出していいか確認されます。

確認ダイアログ

このダイアログをsecurityコマンドの-Aオプションでスキップする手段もありますがすべてのアプリケーションに対して許可を出してしまいます。少し面倒ですが、ここは一手間かけておいたほうがいいでしょう。

TumblrからJekyll + Github Pagesへ

3年ほど前にWordPressからTumblrへ移行しました。特に大きな問題があったわけではないのですが、最近ソースコードを挿入した記事をいくつか書こうとしたところTumblrのMarkdownではうまく表現され切れない点にすこしストレスを感じていました。表示をあれこれいじっている時間ももったいなくなってきたのでいっそのこと、GFM (GitHub Flavored Markdown)で書けるようなサービスか、システムに移行しようと考え始めました。

あれこれ調べているうちに、どうやらJekyllをつかってGithub Pagesへ移行するのがスムーズそうだなと調べ始めて評価し、次の点で問題なさそうだったので移行することにしました。

  • GFMで書ける
  • 既存のURL構成を引き継げる
  • Tumblrからの記事取り込みもできる
  • シンプルなテーマがある

逆に移行に当たってできなくなる機能もあります。たとえばソーシャルメディア連携です。Tumblrでホストしてもらえば、Tumblr上のソーシャルメディアでリブログなど拡散手段があります。ほかには予約投稿やTwitter連携といった機能も使えなくなります。このあたりはトレードオフですが、ソーシャルメディアで拡散していただくよりも、そもそも記事が書きづらくて筆無精になるのであれば優先順位は明らかです。

ソーシャルメディア連携もあとからIFTTTなど何か使えば実現できるでしょうし、予約投稿も必要になれば決まった時間にgit pushするよう何か構成を考えればいいだけです。

移行の効果

移行中のあれこれは後述することにしてまずは、移行によってどういったメリットがあったかみてみます。

WordPressから移行した際にはサイトの速度が劇的に改善しましたが、今回は比較的軽微な差に収まっています。

TumblrでのPageSpeed結果

まずはTumblrでのPageSpeed計測結果から。

Tumblr / モバイル

モバイル用のスコアは67点。画像サイズが大きいと警告がでているのと、キャッシュ設定などのところで最適化の余地があるとの判定です。

Tumblr / デスクトップ

デスクトップ用のスコアは77点。モバイルと同様に画像が大きいと警告が出ています。いずれにしても体感的にはもっさりした感覚は全くなく、表示速度などの不満は特にありませんでした。

Jekyll + Github PagesでPageSpeed結果

Jekyll + Github Pages / モバイル

モバイル用のスコアは72点と少しだけTumblrでの表示より改善しています。これはTumblrのインフラスピードとの差というよりは、採用しているテーマのCSSやJavaScriptの差がほとんどだと考えられます。

Jekyll + Github Pages / デスクトップ

デスクトップ用のスコアは77点とTumblrでの結果と同じです。

その他の違い

Tumblrではモバイル対応していないテーマを使っていたので、TumblrのUIが優先して表示されています。一方、Jekyllで今回利用したLanyonはモバイルフレンドリーなテーマで、今回どちらでも同じLook and Feelでサイトを表示できるようになりました。

移行

移行作業はJekyllの使い方を覚えるところから全部でおおよそ5〜6時間かかったかと思います。Jekyllはかなり活発に開発されているようなのであまりここで細々と手順を書いてもすぐ使いもにならなくなってしまう気がするのでおおまかな流れだけご紹介しておきます。

Jekyll環境の設定

最近はこの手のツールを使うときはすべてDockerを使って独立した環境で実行するようにしています。再現性もありますし、手元の環境もシンプルに保てます。Jekyllを使うには既存のDockerイメージを使えば充分ですが、いくつかテーマを試したりしているうちに依存関係のあるライブラリをまとめてイメージとして持っていたほうが便利だったので次のような内容のDockerfileを作っています。

FROM jekyll/jekyll:builder

RUN apk add --no-cache --virtual build-dependencies build-base
RUN apk add --no-cache libxml2-dev libxslt-dev
RUN apk add --no-cache ruby-dev curl-dev zlib-dev yaml-dev
RUN gem install nokogiri
RUN gem install minima
RUN gem install jekyll-import

jekyll-importは後述のTumblrから記事を取り込んだときに使ったものです。このDockerfileをビルドしておきます。たとえばsiteディレクトリ以下につくっていくならこんな感じにコンテナを実行して、テンプレートを作ったりjekyll-importを実行したりできます。

$ docker run --rm -i $(pwd)/site:/srv/jekyll -p 4000:4000 -t (ビルドしたときのタグ名) bash

今回はあれこれテーマをダウンロードし、jekyll-importでTumblrから記事をざっくり取り込んで表示確認をしながらレイアウトを決定しました。

Tumblrからのインポート

jekyll-importのTumblrについての記事にコマンドが書かれていますのでこれを実行します。 移行といっても今回はTumblrで書いた記事が12記事しかなかったので、ある程度の部分は詳しく調べずに手作業でファイルを修正していくというスタイルで解決しました。

今回実行した際は次のように実行しました。

ruby -rubygems -e 'require "jekyll-import";
    JekyllImport::Importers::Tumblr.run({
      "url"            => "http://(TumblrのID).tumblr.com",
      "format"         => "html",
      "grab_images"    => true,
      "add_highlights" => true,
      "rewrite_urls"   => true
    })'

最初formatはMarkdown(md)を指定していましたが、うまく記事が取りこめなかったのでhtmlで取り込み、あとで手動でMarkdownに変換しました。

Tumblrでは記事のURLが /post/(記事ID)/(記事タイトル)というフォーマットでしたが、Jekyllでは/(年)/(月)/(日)/(記事タイトル)となるので変換が必要です。rewrite_urlsで相当するアドレスにリダイレクトするファイルを作ってくれるので、リンクはそのまま維持できます。

ただ困ったことに生々されたリダイレクト用のindex.htmlでは/(年)-(月)-(日)-(記事タイトル)へのリダイレクトになっていてうまく動きません。あれこれ探すのも面倒だったのでここは手動で直してしまいました。

grab_imagesという設定があり画像をもってきてくれそうな印象がありましたが、これもうまく動かなかったので手作業で画像をもってきたり、手元に保存してあったものを使ったりして再構成しました。

テーマ選び

いくつかサンプルを見ながら選びましたがシンプルなものがよかったのでLanyonにしました。ほかにもシンプルなデザインのものはありましたが、Lanyonは欲しい機能がおおむね入っていることと、CSSやJavaScriptを含めても全体の構成がシンプルで全体が見渡しやすいことが気に入りました。

切り替え

できあがったJekyllのページ一式をGithub Pagesへプッシュし、あとはCloudFlareでDNSの切り替えをすれば終了です。

Jekyllも開発スピードが速そうなので、開発についていくとしたらかなり大変そうです。ただでき上がったサイトはかなりシンプルなHTML、CSS、JavaScriptと画像ファイルだけで構成されているのでセキュリティー上の理由などで更新しなければいけないケースはかなり少ないと思います。

そういった意味では、一度環境ができ上がってしまえばTumblrでプレビューにあれこれ悩みながら記事を書くよりも手元の環境で確実なプレビューを見てから公開できるワークフローをつくったほうがより生産性が高そうだということで今は満足しています。

画像を含めたオーサリングのワークフローをつくったり、プレビューから予定投稿などまでいろいろ作り込みたいところですがそのあたりはまた今度じっくり作り込んでみることにします。