読者です 読者をやめる 読者になる 読者になる

あんパン

こしあん以外は認めない

Windows 10とUbuntu 16.10 on LVM on LUKSを1つのマシンに同居させる

これの続き。

前回はrootとswapを別のパーティションに作成したため、起動時にパスワードを2回入れる必要があった。まあこれでも良いのだが、煩雑なので1回で済ませられるようにしたい。そこで、LVM on LUKSを試してみることにした。暗号化した1つのパーティション上にLVMで複数の論理ボリュームを作成し、rootとswapを割り当てる。

参考にしたのは以下。

www.youtube.com

上記動画ではUEFIブートを前提としていないので若干手順が異なる。


前回と同様にWindowsのディスク管理でCドライブを縮小しLinuxのインストール領域を作る。unetbootinでUbuntu Desktop 16.10のインストールディスクを作っておく。

一旦シャットダウンしてインストールディスクから起動し、GPartedで未割り当ての領域に以下のようにパーティションを作る。

  • /boot用のパーティション: ext2, 500MiB (ここでは/dev/sda5)
  • /用のパーティション: ext4, 残り領域すべて (ここでは/dev/sda6)

このとき、/用のパーティションにはlvmフラグを立てておく。

端末を開いて以下のコマンドを順番に実行する

$ sudo -i
# cryptsetup luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 2000 /dev/sda6
# cryptsetup luksOpen /dev/sda6 sda6-crypt
# pvcreate /dev/mapper/sda6-crypt
# vgcreate UbuntuVG /dev/mapper/sda6-crypt
# lvcreate -C y -L 16G -n swap UbuntuVG
# lvcreate -C n -l 100%FREE -n root UbuntuVG

やっていることは以下の通り

  • cryptsetup luksFormat/dev/sda6を暗号化
  • cryptsetup luksOpen/dev/mapper/sda6-cryptにマウント
  • pvcreateでLVMの物理ボリュームを初期化
  • vgcreateで物理ボリューム上にボリュームグループを作成
  • lvcreateでボリュームグループ上に論理ボリュームを2つ作成
    • -Cオプションは論理ボリュームを隣接させるかどうかのオプション
    • -Lオプションはボリュームのサイズを指定するオプションで、16Gなど数値で明示的に指定する
    • -lオプションはボリュームのサイズを指定するオプションで、100%FREEのように割合で指定できる

ここまで実行したら、インストーラを起動して通常通りインストールする。なお、ここではサードパーティのアプリケーション等をインストールしない。

インストール先の選択では「それ以外」を選んで

  • /dev/UbuntuVG/rootをext4で初期化して/をマウントポイントに指定
  • /dev/UbuntuVG/swapをswap領域に指定
  • /dev/sda5をext2で初期化して/bootをマウントポイントに指定
  • ブートローダのインストール先を/dev/sdaに指定

を行い、インストールを続ける。一通り実行したら、再起動せずにUbuntuの試用を続ける。

再び端末を開いて以下を行う

$ sudo -i
# mount /dev/mapper/UbuntuVG-root /mnt
# mount /dev/sda5 /mnt/boot
# mount /dev/sda2 /mnt/boot/efi
# cd /mnt
# mount --rbind /dev dev
# mount --rbind /sys sys
# mount --rbind /run run
# mount --bind /proc proc
# chroot . /bin/bash -l
(chroot)# echo "sda6-crypt UUID=/dev/sda6のUUID none luks,discard" > /etc/crypttab
(chroot)# update-initramfs -u
(chroot)# grub-install --recheck /dev/sda
(chroot)# grub-mkconfig -o /boot/grub/grub.cfg
(chroot)# exit
# cd 
# umount -l /mnt
# sync
# reboot

やっていることは以下の通り

  • mount/mnt以下に作成したパーティションたちをマウントする
    • Windows Boot Managerの/dev/sda2/mnt/boot/efiにマウントしておかないとgrub-install --recheck /dev/sdaで弾かれる
  • /etc/crypttabを作成する
    • 各項目はタブ区切り
    • sda6-cryptは先程luksOpenで使った名前をそのまま使う
    • UUIDは、別の端末を開いてsudo cryptsetup luksOpen /dev/sda6すると表示される
      • sudo blkid/dev/sda6のものを探しても良い
    • noneは鍵の場所指定。今回は鍵がないのでnoneとする
    • luks,discardはオプション。discardはSSDの場合のみつける
      • SSDのパフォーマンスを維持するためTRIMコマンドを使うかどうかの指定
  • grub-mkconfig -o /boot/grub/grub.cfgでブートメニューを更新

あとはchroot環境を抜けてマウントしてたパーティションをアンマウントし再起動する。Ubuntuを起動するとsda6-cryptのパスワードを1回だけ求められ、入力すると起動できる。


これでUbuntu 16.10 on LVM on LUKSの環境を整えられた。Windows側の領域をBitLockerで暗号化している場合は、これらの作業を終えたあとにWindowsを起動する時、初回のみBitLockerの回復キーを入力して起動する必要がある。

Windowsが入っているマシンにパーティションを暗号化した上でUbuntuを同居させる

新型MacBook Proのキーボードをヨドバシ店頭で触ったところ2秒でやっていけないことに気づいたのでThinkPad X260を購入した。ThinkPad EdgeやX201を使っていたこともありX260自体にはなんの不満もなく、安価でそこそこのスペックの製品を買うことができてよかった。

一方で、Windows 10でこれまでMacでやっていたような開発を続けるのは困難だということもわかってきた。最初はLinux Subsystem for WindowsやらPowerShellやらでなんとかなるだろうと見込んでいたものの、その見立ては完全に外れていた。

そこで、Ubuntu 16.10を同居させてデュアルブートできるようにした。Windowsを飛ばしてUbuntuのみにしなかったのは、ひとえに紙芝居的なゲームをするため。Ubuntuにしたのは、わざわざOSのメンテにコストをかける気持ちがなかったため。

Ubuntuをデュアルブートするのは簡単で、Windows側でディスクを縮小して、unetbootinでUSBメモリに焼いたインストーラからうまい具合にインストールすれば良い。しかし、パーティションの暗号化をしつつインストールするには一手間必要だったので、ここにメモする。なお、Windowsが入っているパーティションはBitLockerで暗号化している。


基本的にはここの通りにすると良い。ディスクの暗号化にはLUKSを使う。

askubuntu.com

いきなりインストーラを起動するのではなく、GPartedでパーティションを切る。元のサイトでは

  • boot (ext2) - If you have Windows installed with UEFI, this can be skipped,
  • root (ext4),
  • swap (linux-swap)

と書いてあるが、UEFIブートしているにもかかわらずbootパーティションを作らずにインストールしたところ、grubのインストール時にコケたのでどうも必要そうだった。この場合、実際にディスクを暗号化するのはrootとswapのみになる。どちらもパスワードを別個に設定して、起動時には両方のパスワードを入力してマウントすることになる。(が、なぜコケたのか正直良くわかっていないし、本当に使われているのかわからない。誰か教えてくれ!!!)

今回はboot領域を250MiBで確保し、ext4でフォーマットした上でboot,espフラグを立てた。root, swapは上記の通り。適用すると、sda5,sda6,sda7ができた。

次の詰まりポイントはcryptsetup luksFormatだと思う。コマンド自体はこれで問題ないが、Are you sure? (Type uppercase yes):と出て来るので、大文字でYESと記入する必要がある。入力すると、パスワードと確認用にもう一度パスワードを求められるので記入する。これをsda6とsda7それぞれに行う。

それぞれluksOpenでrootとswapでマウントしたら、それぞれmkfs.ext4やらmkswapやらしておく。あとはインストーラを起動して、インストール先の選択時に「それ以外」を選び、パーティションをそれぞれ設定する。sda5は初期化せず、マウントポイントを/bootにする。/dev/mapper/rootのマウントポイントを/に、/dev/mapper/swapはすでにswapになっているはずなのでそのままにする。

通常通りインストールを終えたら、再起動せずにもう一度端末を開く。

リンク先に書いてあるとおりrootやらbootやらをマウントしてchrootしておく。ここで/etc/crypttabを設定する。

root UUID=<uuid> none luks
swap UUID=<uuid> none luks,swap

というような内容になるはず。このuuidはsudo bulkidで探せば見つかるが、sudo cryptsetup luksUUID /dev/sda6などとしたほうが素早く見つかる。別の端末を開いて実行しないと取得できないので要注意。その他詰まりどころはないはずなのでリンク先の通りに実行して再起動すると良い。ちなみにupdate-initramfs -uするときにwarningを吐く気がするけれど、無視して問題ない。

再起動後、rootとswapのパスワードをそれぞれ入力するとUbuntuを起動することができる。

エンジニア立ち居振舞い:サービスを使い倒す

ひとでくんさんが お題「エンジニア立ち居振舞い」 を作っていたので参加します。

toBなサービスを開発しているとなかなか難しいかもしれません。幸いなことに今自分が携わっているプロダクトはどちらかというとtoC寄りなので成り立っています。

サービスを使い倒す

おそらくどのエンジニアも自分が携わっているプロダクトに少なからず愛着を抱いていると思います。嫌いなプロダクトに携わるのではモチベーションが保たないはずです。また、プロダクトが好きなので自ずとドッグフーディング*1をされている方も多いと思います。

しかし、自分がいちユーザであるWebサービスなどでは作業が単純化しがち、特定の機能を使いがちになります。例えばブログサービスであれば、毎日PCから書くだけ、購読しているブログの新着記事を読むだけなど。もちろんこれでも良いといえば良いのですが、自分はなるべく意識的にいろんな機能を使うようにしています。例えば、今日はアプリからブログを書いてみよう、とか、今日は予約投稿してみよう、などを意識的にやっています。この記事はマイお題機能のドッグフーディングということになりますね。

特に今日はこれをする、明日はこれをするというような管理はしていませんが、毎日ブログを書けるようにリマインダを仕込んだりはしています。疲れているときはスキップすることもあります。

f:id:masawada:20161111112334p:plain:w400

このような使い倒しは、いつの間にか意図しない不具合が起きていないかを探すためにも有用ですが、サービス全体の世界観を把握するのにも有用です。新たに着手する機能に必要な挙動などが想像しやすくなりますし、デザイナの提案に対して感想を述べる際の論拠にもなり得ます。特にチームにジョインしたての方には良いのではないでしょうか。

ドッグフーディングをするのは良いことですが、単純に特定の機能のみを使い続けるだけではあまり効果的ではないように思います。意識的にいろんな機能を使い倒すと良さそうです。

Dropboxで静的コンテンツ配信ができなくなったのでS3で代替する

Dropboxで静的コンテンツの配信ができなくなるという話を聞いた。みんなの元にはメールが来ているけど、なぜかぼくの元にはメールがきていない。

www.dropbox.com

2016 年 10 月 3 日より、ウェブ ブラウザで HTML コンテンツをレンダリングする共有リンクの使用が無効になります。Dropbox から直接 HTML コンテンツを表示する方法でウェブサイトを制作している場合、この日付以降はブラウザでコンテンツのレンダリングができなくなります。HTML コンテンツ自体は引き続き Dropbox に残り、共有することもできます。

な る ほ ど

という感じで、みんな割と使ってる機能だろうし不便だと思う(課金勢は来年くらいに使えなくなるらしい)。あまりに不便なので、なにか別の方法でおなじようなことを実現できないかと思って、S3を変わりに使う方法を思いついた。といってもS3で静的コンテンツを配信する方法は世の中にありふれていると思う。

なので、ここで書くのはS3を静的コンテンツ配信に利用しつつちょっと便利に使う方法ということになる。

S3をマウントする

S3を操作するにあたっていちいちコマンドを叩いていたら日が暮れるので、バケットをマウントして普通のファイルシステムみたいに触れるようにする。S3をマウントする方法はいくつかあるけれど、Transmitを使うと便利だった。

Transmit

Transmit

  • Panic, Inc.
  • ユーティリティ
  • ¥4,100

TransmitはWeb系のクリエイターなら名前は聞いたことがある(?)Codaというエディタを作っているPanic社のFTPクライアント。有料だけど結構いろいろな機能がついていて便利なので昔はよく使っていた。S3をマウントできるというのは結構前に見ていたのでこれならいけるのでは、と試してみたらいい感じにうごいてよかった。

f:id:masawada:20160921104124p:plain

こういう雰囲気でマウントできる。謎のなんちゃらfuseみたいなのを入れるよりかは精神的に良いという印象。

Automatorで共有リンクを引っ張ってこられるようにする

単純に放り込んだだけだと共有リンク作るのが面倒くさいので、コンテキストメニューから呼び出せるようにする。Automatorを使うとうまくいく。Automatorで新規サービスを作成して以下のような設定で保存すると良い。

f:id:masawada:20160921130423p:plain

これで、右クリックからコンテキストメニューで公開URLを取得することができる。

f:id:masawada:20160921130532p:plain

なお、保存したサービスの居場所がわからなくなりがちだが、キーボードショートカットの設定あたりにしれっといる。ここからショートカットを指定することもできるし、右クリックするとAutomatorで開き直したりFinderでそのディレクトリを呼び出したりすることができる。

f:id:masawada:20160921130635p:plain

そのほかやったこと

CloudFront通したり、Route 53でドメイン取得しつつCNAME設定したりということをした。SSL証明書もタダで、一瞬で作れてすごい。いまのところ自分の公開バケットは https://files.masawada.me あたりから覗くことができる。S3もCloudFrontもRoute 53も異常に安価なので破産することはないと思いつつ、5ドル上回ったら支払いのアラートが飛ぶように設定しておいた。これでお財布も安心だと思う。

不便な点

ここまでやったは良いものの、やはりフォルダに突っ込むと勝手にアップロードしてくれるDropboxは便利だと思う。S3の方はファイルシステムにマウントしているもののアップロードに割と時間がかかる。リージョンをTokyoにしていても時間がかかるので、こういうものだと諦めるしかなさそう。

まとめ

Amazonすごくて、雑にぽちぽちしただけで静的コンテンツを配信できるようになる。ありがたく使いましょう。

ISUCON6予選やった

Iikanji Speed Up CONtestというのが毎年あって、それの第6回の予選に出た。2日目日曜日の方。去年も出ていたのだけど、全く意味わからなかった。今年は少しマトモで、決勝こそでられなかったもののそこそこのスコアになったので満足といった感じ。これくらい↓

f:id:masawada:20160920225037p:plain:w200

一つ情報を追加しておくと、前日の夜くらいまで38度近い熱があって死んでいた。当日の朝に36度台に下がって、ISUCON終了ごろには37.5度というステータスだった。

それはさておき僕がやったことは以下4点。なお言語はPerlです。

  • isutarのisuda統合
  • キーワードリストをmemcachedに載せる
  • ページングをmemcachedでやる
  • is_spam_contentのレスポンスをキャッシュに載せる

isutarのisuda統合

ぱっと見たときに、isuda.psgiとisutar.psgiがあって最悪な気持ちしかなかった。幸いにもisutarにはマトモな仕事をしているエンドポイントが2つしかなく、テーブルもstar1つのみだったので、まるまるisudaに移動した。$c->dbh$self->dbhに書き換えるとかそういうのはあったけどほぼまるまるコピペ+Furl使ってるところを直接DB見に行くようにするのと、isutarDBのテーブルをisudaDBに作り直す、くらい。show create table star\G;みたいなの発行するとそのままCREATE TABLE文が出てくるのでそれをisudaで発行しただけ。30分もかからず終わったと思う。

キーワードリストをmemcachedに載せる

htmlifyを叩く度にキーワードリストを生成するために

SELECT * FROM entry ORDER BY CHARACTER_LENGTH(keyword) DESC

でエントリのリストを生成してからmap { $_->{keyword} } @$keywordsみたいなことしててとにかくDBの帯域を食っているイメージだったので、新たにキーワードを登録する度に全キーワードを文字数降順でソートした配列を再生成してmemcachedに載せておいて、それを使うようにした。これは意外と効いてスコアが2700くらいから一気に1万超えをはたした。

ページングをmemcachedでやる

一般にMySQLのOFFSETは遅い。実際に50ページ目くらいのリクエストのmean response timeが結構大きくなっていたので試しにやってみようみたいな話になった。上のキーワードリストと同じようにupdated_atの降順でキーワードリストを生成しておいて、そこからページャを生成したりした。これはあまり効果なかった気がする(2000くらいは上がった)

is_spam_contentのレスポンスをキャッシュに載せる

キーワード登録時にisupamにコンテンツがスパムかどうかを問い合わせていそうだった。is_spam_contentの中でFurlでhttpリクエストを発行していて、これが無駄だなーと思っていたので試しにis_spam_contentの引数のsha1_hexとisupamのレスポンスの組をキャッシュしたところ、一気にスコアが40,000超えするようになった。 isupam自体はどうせ特定の単語に反応してvalid/invalidを返すだけだろう(しかもその単語はそれほど多くない)という予想をしていたし、isudaに突っ込まれるテキストもWikipediaから引っ張ってきたいくつかの記事だけだろうという予想もあったのでやってみたところ異常な効果があった。しかもベンチの回を重ねるとスコアが伸びてよかった。最終的に65000くらいで頭打ちになったけど、だいぶ効果があったのではと思う。

そのほか

こうやってみるとキャッシュ載せるくらいしかやってないな… 結局いろいろやったけどキーワードリストをmemcachedに載せるのとis_spam_contentのレスポンスをmemcachedに載せるのくらいしか効果はなかった気がする。正規表現のところボトルネックになってるだろうなーと思いつつこれ時間内にほぐす自信ないなという気持ちであまり手を入れなかったけど、普通にもう少し手を入れたら良かった気がする。そうしたらもうちょいスコアあがった気もする。

とはいえ実は最初の3時間くらいは初期スコア0に悩まされてなにもしてなくて、最後の30分くらいは再起動テストでなにもしていなかったので、実質の作業時間は4時間ちょっとだった。時間的にもあまり余裕はなかったので、来年はこんなことのないように頑張っていきたい。今年全然なにもしてなかったけどアプリケーションのプロファイルとかもとったほうが良さそうですね。。

全体を通して、普通のWebサービスじゃ絶対にやらないでしょみたいな雑な対策/雑なコードを量産してあれくらいのスコアまでいくのかーという知見が得られて面白かった。Perlmemcached扱う方法とか学べてよかった。

さいごに、一緒に戦ってくれたid:masayoshiくんid:taketo957くんありがとうございました、最高すぎた。来年もできればお願いしたいです:pray:

YAP(achimon)C::Asia Hachioji 2016 mid in Shinagawa ネット担当を支える技術

7/2, 7/3は YAP(achimon)C::Asia Hachioji 2016 mid in Shinagawa でした。ぼくはネット担当(Twitter担当)としてスタッフをしていました。

今回は快適にTwitterを監視する技術を紹介します。

ネット担当とは

各担当の仕事についてはGitHubWikiに記載されています。

github.com

当日の業務としては

  • 各部屋の写真を流す
  • 飛び入りトラックの情報を流す
  • Wi-Fi情報や受付で困っている人がいたら声をかける
  • 落とし物情報を流す
  • 資料アップロード報告などのツイートをRT
  • そのほか諸情報を流す
  • Togetterでまとめる

という感じでした。主にTwitterに張り付いている仕事です。基本的に張り付いていて1日目は1つもトークを見ておらず、2日目に2,3本だけ見ました。(が、一番聴きたいトークを聴けた&&ちょっとしたうれしいことがあったので最高でした)

このTwitter監視業務をするに当たって便利なツールを作成したのでご紹介です。

作ったもの

特定のハッシュタグ/単語を含むツイートをSlackに流すアプリケーションです。Herokuにデプロイできます。

github.com

特にREADMEとか書いてないんですが、適当にポチポチすると完成するので特に解説不要だと思います。

なぜSlackに投稿するのか

特定のワードで検索しながらTwitterを眺めるだけであれば、TweetDeckでも良いと思います。しかし、以下の点でTweetDeckでは不十分でした。

  • Win/Mac/Linuxで使えるようにしたい
    • 何が起きても最悪ブラウザなどで見たい
  • バイルでも同じ環境がほしい
  • ツイートを通知したい

本来であれば専用にUIを用意してSocket.IOなどでリアルタイムに表示して監視するのが筋だと思います。しかし、ただ監視するために無駄に凝ったものを作るのは達成したいことに対してあまりにも手間がかかりすぎます。そこで、Twitterで特定のキーワードを拾ってSlackに投稿するようにしました。

Slackに投稿することにより、以下のようなメリットも生まれました。

  • 未読管理ができる
  • お問い合わせなどにreactionをつけると誰かが対応したことがわかって便利
  • 特定キーワードのみをハイライトした上で通知できる
  • 難しい実装を考えなくてよくなる
    • データベースなどを考えなくても過去のツイートをさかのぼれる
    • XSSなどを考慮する必要がない

特に、未読管理とキーワードのハイライトは役に立ちました。

懸念点と実際の運用

Herokuにデプロイボタンを用意していますが、実運用はVPSで飼っているdokkuに任せました。

運用にあたって、以下が懸念点でした。

  • ハッシュタグをつけてくれる人がどれだけいるのか
    • statuses/filterを利用していたので、ファジーな検索ができない
  • Slackのrate limitに引っかからないか
  • 無料枠でさかのぼれる10000件を超えないか

結局のところ流量は異常に速いということもなく、2日間安定して運用することができました。当日朝まではハッシュタグを使用している人はほとんどいませんでしたが、開始以降はだいぶ使われており、ヤパチーに関するほとんどのツイートを拾えていたのでは(?)と思います。また、無料枠の点に関しては、運営用に使用していたチームとは別のチームを作成してそちらに投稿することで、運営側に迷惑をかけることなく利用することができました。

実際に活用していたのは自分だけだったのですが、特定キーワード(資料アップロードなど)を監視して通知することで割と素早く反応できたのではないかと思います。

f:id:masawada:20160703235305p:plain

こういう雰囲気でした。ツイートのリンクを表示しておくことで、 PCではTwitterWebから、モバイルではTwitterAppから反応することができてだいぶ便利でした。

まとめ

という内容を飛び入りトラックで5分くらいつかってやろうと思っていたのですが、あまりネタにならないなーと思ったのと、単純に睡眠不足で疲れていてスライドを生成できなかったのでここに公開します。普通に使っていて便利だったので簡単な監視ツールとして是非ご利用ください。

git diffで差分のあるファイルを一瞬で開くやつ

編集してまだgit addしてないやつをもう一度開きたいとき,いちいち探るの面倒なので作った.多分この世に既にごまんとあると思う.

gitのサブコマンドとして作るならこんな感じ

FILE_PATH=$(git diff --name-only | peco)
if [ ${#FILE_PATH} -ne 0 ]; then
  $EDITOR $(git rev-parse --show-toplevel)/$FILE_PATH
fi

zshの関数として作るならこんな感じ

function peco-git-editdiff {
  local dir=$(git diff --name-only | peco)
  if [ ${#dir} -ne 0 ]; then
    BUFFER="${EDITOR} ${dir}"
    zle accept-line
  fi
  zle clear-screen
}
zle -N peco-git-editdiff
bindkey '^e' peco-git-editdiff