Unyablog.

のにれんのブログ

軽い Shell を作った

↓の記事を読んで自分でもサクッと作れそうなので作ってみた。

brennan.io

名前は nsh (nonylene shell の略)。記事を参考にコードを書いていたら大体同じようなものになってしまった。

github.com

記事では C で書いているけど、nsh では Python3 で書いてみた *1。結局パースで6割ぐらい占めていて、コマンドを実行するのはこの部分だけ。

def execute_line(args):
    pid = os.fork()
    if pid == 0:
        os.execvp(args[0], args)
    elif pid < 0:
        print("error with fork!")
    else:
        while True:
            wpid, status = os.waitpid(pid, os.WUNTRACED)
            if os.WIFEXITED(status) or os.WIFSIGNALED(status): break

それなりに使えるようになったので満足。

f:id:nonylene:20161209003000p:plain

fork して execvp している以外は通常の Python の処理なので、特段困ったこともなく一時間ぐらいで作れたので良かった(小並感)。

*1:今考えたらシステムコール打ちたい時に困りそうだけど、軽く作って見る分には os.fork や os.execvp を使う程度だったので大丈夫だった。

サーバーを ConoHa に移行した

サーバーを家の Raspberry Pi から ConoHa に移行しました。

理由は単純に Raspberry Pi ではいろいろするのに辛くなってきたのと、最近謎のエラー*1により SEGV することが多くなって悲しくなってきたためです。カーネルの Early Memtest 使って軽くメモリチェックしてみたり microSD の r / w チェックしたりしてみたけど特に異常も無くてよく分からなかった。

ConoHa にした理由は特に無くて、強いて言えばスペックが後から変更できることですが、だからと言って変更することはなさそう。

VPS の作成は速いし、コンソールもシンプルで使いやすいので良いと思います。

管理

ついでに Ansible で管理していたのを itamae に置き換えました。Ansible は Python のバージョンが面倒だったのですが itamae はそういった事もないので良いですね。

ConoHa は IPv6 アドレスを 17 個もらえるのですが、まだメインの 1 つしか使っていないのでどうしようかなと考えているところ…。

https://nonylene.net

ついでに HTTPS 化しました。Let's encrypt でシュッと作成して設定しただけです。/blog/ とか Mixed Contents 入りまくってますがもう使ってないので放置してます...(テンプレート直して jekyll 回すだけ)。

更新もletsencrypt renew を cron で回せばいいので楽ですね。

退役した Raspberry Pi は家の温度取得したりエアコン操作したり目覚ましにしたりできればいいなあと思っています。目覚ましは omxplayer 使ってスピーカー鳴らせばすぐできそうな気がする。

*1:relocate で死ぬ

Android Studio をビルドする

この記事は KMC アドベントカレンダー 4日目の記事です。自分は5日目だと思っていてのんびりしてました… :bow: :bow:

www.adventar.org

昨日は id:nojima718 さんの

nojima.hatenablog.com

でした!

本題

今回は Android Studio をビルドしてみます。

大体ここに従ってます。

tools.android.com

何故

Android Studio 2.2 になってから mac で外部ディスプレイに繋げたときに色が全体的に色が濃くなりました。僕の使ってる Molokai テーマには致命的で、元からコントラストが高いのにさらに濃くなると目が痛くて仕方ありません。

だからといってテーマ変えても濃くてつらく、最近は外部ディスプレイに繋がずに使っていました。

ここで Android Studio の更新ログを見ると

Improved color management on OS X

とのこと。

もしこれのせいなら、 該当する Commit を Revert して自分でビルドすればいいのでは? と思い立ち、とりあえず自分でビルドしてみることにしました。

ちなみに原因はそれではありませんでした(後述)。

ビルド

ソースコード

repo

Android では複数の git repository を一度に扱う repo というコマンドで管理することを推奨しています。*1

Repo command reference | Android Open Source Project

上に従って repo (実体は Python スクリプト) をダウンロードして実行できるようにします。

repo sync

次は適当な場所にソースコードをダウンロードします。とりあえずビルドしてみるだけなので --depth=1 としてファイル容量を抑えています。*2

$ mkdir studio
$ cd studio
$ repo init -u https://android.googlesource.com/platform/manifest -b studio-2.2.2 --depth=1
$ repo sync

大量のレポジトリが 3GB ほど降ってきます。後のビルドでも 5GB 程度は容量食うのでそれなりに確保しておきましょう。

ビルド

とりあえずビルドしてみます。ドキュメントにある通り、 ant をインストールした後

$ cd tools/idea
$ ant

とすれば後はビルド終了を待つのみ。

自分の Macbook では 20 分ほどかかりました。ポケモンピクロスでもして待っていましょう。

成果物

tools/idea/out/artifacts 以下にビルドした AndroidStudio 達が存在しています。Mac でビルドしましたが Windows / X Window 用も作られていました。

$ ls out/artifacts
android-studio-SNAPSHOT-no-jdk.mac.zip
android-studio-SNAPSHOT-no-jdk.tar.gz
android-studio-SNAPSHOT-no-jdk.win.zip
core
intellij-core-AI-145.SNAPSHOT.zip
jps
sources.zip

ここから android-studio-SNAPSHOT-no-jdk.mac.zip を解凍すれば Android Studio.app が生成されます。こうして自分専用の Android Studio が使えるようになりました。

JDK

ところでファイル名を見ると no-jdk となっており、Idea JDK が含まれていないようです。なくても困ることはないですが、推奨されているのだから使いたい。

どうやら prebuilts/studio/jdk に然るべき JDK を置けば一緒に含めてくれるみたいです。

ということで、repo のレポジトリ管理ファイルである manifest.xml に新しいレポジトリを追加します。

ローカルの manifest.repo/local_manifests に置けば良いので、.repo/local_manifests/manifest.xml

<?xml version="1.0" encoding="UTF-8"?>
<manifest>

  <remote  name="aosp"
           fetch=".."
           review="https://android-review.googlesource.com/" />

  <project path="prebuilts/studio/jdk" name="platform/prebuilts/studio/jdk" clone-depth="1" revision="studio-master-dev"/>

</manifest>

と記述して repo sync します。

すると prebuilts/studio/jdkplatform/prebuilts/studio/jdk (https://android.googlesource.com/platform/prebuilts/studio/jdk/) の studio-master-dev ブランチが clone されるので、再ビルドすると

$ ls out/artifacts
android-studio-SNAPSHOT-no-jdk.mac.zip
android-studio-SNAPSHOT-no-jdk.tar.gz
android-studio-SNAPSHOT-no-jdk.win.zip
android-studio-SNAPSHOT.mac.zip
android-studio-SNAPSHOT.tar.gz
android-studio-SNAPSHOT.win.zip
android-studio-SNAPSHOT.win32.zip
core
intellij-core-AI-145.SNAPSHOT.zip
jps
sources.zip

が生成されました。

しかし、実行してみると起動してくれない…。ブランチが違ったりしてるし諦めて JDK 無しでやりました。

その後

実行できたので早速 git のログを漁り初めたのですが、それっぽいログがない。実際にソースを見てみてもそれっぽい部分がないので困っていると、ちょうどそれらしきプラグインを発見。*3

github.com

どうやら問題は IntelliJJDK を Idea JDK (8) に切り替えたことが原因のようです。

https://youtrack.jetbrains.com/issue/IDEA-149601

...ということでプラグインを入れることで問題が解決してしまった🙏。*4

ビルドが終わった頃には studio ディレクトリは 12GB も食っていました。残り容量はなんと 500MB になり、警告も出ています。

よって、速やかに studio を削除してこの話は終わりとします。ありがとうございました。

$ df -h 
Filesystem      Size  Used Avail Use% Mounted on
/dev/disk1      186G  185G  529M 100% /
/dev/disk0s4     47G   27G   21G  57% /Volumes/BOOTCAMP
$ rm -rf studio
rm -rf studio  0.81s user 20.83s system 60% cpu 35.700 total
$  df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/disk1      186G  173G   13G  94% /
/dev/disk0s4     47G   27G   21G  57% /Volumes/BOOTCAMP

余談

  • Cross Compile...?

Windows 用はどうやって作っているのだろうと見たところ、ある程度の exe は初めから置いておいて、最後は気合の実装で作るという感じでした。すごい。他のプラットフォームも割りとそういう感じ。

intellij-community/tools/launcher-generator/src/com/pme/exe at master · JetBrains/intellij-community · GitHub

ということは何か将来個人的な変更を加えたい場合は、 CI に投げて自動的に MacWindows 用の AndroidStudio を作るといったことができそう。

  • 容量問題

ソースコードを見たいだけなら https://android.googlesource.com/platform/ から見たいものを clone するだけで良いです。ビルドにはいろいろ必要ですが、見るべきなのは一つのリポジトリ程度なので。

また、intellij 本家を GitHub で見るのもオススメです。

github.com

明日

明日(今日)は id:tyage さんです!!!楽しみですね!!!

*1:使わなければ一つ一つレポジトリを clone していくことになりめんどくさい

*2:depth を付けないと 8GB ほど埋まるので注意

*3:偶然にもこの方の IntelliJ 用 Molokai テーマを弄ったものを使っていた

*4:まだ試してませんが

curl: (60) SSL certificate problem: certificate is not yet valid

対処

時刻がおかしいので ntp とか入れる

経緯とか

久しぶりに VirtualBox で入れていた Arch Linux を起動して、 bundler が入っていなかったので gem install bundler を打つと、

certificate verify failed

とのエラーが *1

確かに curl https://rubygems.org しても上手くいかないし、 curl http://google.com も無理。でも github は上手くいくから何故だろうと思っていた。

$ curl https://google.com
curl: (60) SSL certificate problem: certificate is not yet valid

と言った感じ。(ここでちゃんとログを見ればすぐ解決してた...)

ルート証明書が古かったりおかしかったりするのかなと思ったけど /etc/ssl にちゃんとあるし、変ですねと思ってもう一回ログを見たら "not yet valid" って言ってる。

もしかして時間・・・?と思って date したら内部の日付が一ヶ月半前だった。そりゃダメだ。

Arch, デフォルトでは ntp で同期してないんですね。

結局

# pacman -S ntp
# systemctl enable ntpd.service
# systemctl start ntpd.service

したら直った。

追記

Systemd にそもそも組み込まれていたのでそっちを ON にすればいいという指摘をもらった。ということでそっちを使うように。

# pacman -R ntp
# timedatectl set-ntp false
# timedatectl set-ntp true

一度 false にしないと、 NTP synchronizedno のままだった。

*1:詳しいログまでは記憶してない

Kotlin の String#split で正規表現を用いる

Kotlin の String#split は、 String を引数に取った場合 Regex を使用しません。 正規表現を用いて split を行うには、Regex を引数に取る必要があります。

java

"hogehoge piyo  foo".split("\\s+")
// => ["hogehoge", "piyo", "foo"]

kotlin

  • Bad
"hogehoge piyo  foo".split("\\s+")
// => ["hogehoge piyo  foo"]
  • Good
"hogehoge piyo  foo".split(Regex("\\s+"))
// => ["hogehoge", "piyo", "foo"]

Android の df コマンドについて

最近 Android 用の mackerel-agent を作ろうとしていて、Android/proc/meminfo を読んだりしていたのですが、 filesystem の metrics は df -P コマンドを使っていました。*1

Android にも df コマンドは存在していたのでパースしようとしたのですが、バージョンごとの違いなどがあったのでメモ。

バージョンによる挙動

Andorid 6.0.1 (Marshmallow) まで

$ adb shell
shell@SO-02H:/ $ df
Filesystem               Size     Used     Free   Blksize
/dev                   889.4M   104.0K   889.3M   4096
/sys/fs/cgroup         889.4M     0.0K   889.4M   4096
/sys/fs/cgroup/memory: Permission denied
/mnt                   889.4M     0.0K   889.4M   4096
/tmp                   889.4M     4.0K   889.4M   4096
/system                  4.9G     3.9G     1.1G   4096
/data                   21.9G    12.1G     9.8G   4096
/oem                   503.7M   340.1M   163.6M   4096
/cache                 341.0M   304.0K   340.7M   4096
/rca                     8.4M     6.4M     1.9M   1024
/idd                    14.0M     4.9M     9.0M   1024
/persist                27.5M   804.0K    26.7M   4096
/firmware               80.0M    56.5M    23.5M   16384
/lta-label              11.7M     1.1M    10.6M   4096
/storage               889.4M     0.0K   889.4M   4096
/mnt/runtime/default/emulated: Permission denied
/storage/emulated       21.9G    12.1G     9.8G   4096
/mnt/runtime/read/emulated: Permission denied
/mnt/runtime/write/emulated: Permission denied

Android 6.0 までの df コマンドは coreutilsdf とは大きく異なります。

マウントされた先しか見ることが出来ない他、 -h などのオプションは一切使えません。

$ adb shell
shell@SO-02H:/ $ df -h
Filesystem               Size     Used     Free   Blksize
-h: No such file or directory

Android 7.0 (Nougat) 以降? *2

$ adb shell
bullhead:/ $ df
Filesystem                                             1K-blocks     Used Available Use% Mounted on
tmpfs                                                     922680      428    922252   1% /dev
tmpfs                                                     922680        0    922680   0% /mnt
/dev/block/dm-0                                          2999516  2430552    552580  82% /system
/dev/block/dm-1                                           241908   184160     52752  78% /vendor
/dev/block/platform/soc.0/f9824900.sdhci/by-name/cache     92656     4504     86188   5% /cache
/dev/block/platform/soc.0/f9824900.sdhci/by-name/modem     88016    56720     31296  65% /firmware
/dev/block/dm-2                                         26094648 12222956  13855308  47% /data
/dev/fuse                                               26094648 12222956  13855308  47% /storage/emulated

Android 7.0 では coreutils と同じ形式になりました。

-h-P などのオプションも使えるようになり便利。

$ adb shell
bullhead:/ $ df -h
Filesystem                                             Size  Used Avail Use% Mounted on
tmpfs                                                  901M  428K  901M   1% /dev
tmpfs                                                  901M     0  901M   0% /mnt
/dev/block/dm-0                                        2.8G  2.3G  540M  82% /system
/dev/block/dm-1                                        236M  180M   52M  78% /vendor
/dev/block/platform/soc.0/f9824900.sdhci/by-name/cache  90M  4.3M   84M   5% /cache
/dev/block/platform/soc.0/f9824900.sdhci/by-name/modem  86M   55M   31M  65% /firmware
tmpfs                                                  901M     0  901M   0% /storage
/dev/block/dm-2                                         25G   12G   13G  47% /data
/dev/fuse                                               25G   12G   13G  47% /storage/emulated

細かい話

  • Android 6.0 までの実装は以下にあり、Android toolbox に含まれていました。/proc/mounts から読み取っていますが特にオプションを受け取るなどは行っていません。

platform_system_core/df.c at marshmallow-release · android/platform_system_core · GitHub

  • Android 7.0 からは df の実装が toybox に置き換わったので、POSIX に準拠するようになりました。

Lose df to toybox. · android/platform_system_core@cca6019 · GitHub

toybox とは linux コマンド群の BSD ライセンス実装です*3

おまけ

toybox 自体は 6.0 から Android に取り込まれているので、toybox を使えば 6.0 でも新しい df を使えました。

$ adb shell
shell@SO-02H:/ $ toybox df
Filesystem      1K-blocks       Used  Available Use% Mounted on
tmpfs              910748        104     910644   1% /dev
none               910748          0     910748   0% /sys/fs/cgroup
tmpfs              910748          0     910748   0% /mnt
tmpfs              910748          4     910744   1% /tmp
/dev/block/dm-0   5174428    4054116    1103928  79% /system
/dev/block/bootdevice/by-name/userdata 22994780   12698312   10280084  56% /data
/dev/block/bootdevice/by-name/oem 515776     348284     156844  69% /oem
/dev/block/bootdevice/by-name/cache 349136        304     341624   1% /cache
/dev/block/bootdevice/by-name/diag 14327       5165       8835  37% /idd
/dev/block/bootdevice/by-name/persist 28144        804      26688   3% /persist
/dev/block/bootdevice/by-name/modem 81872      57824      24048  71% /firmware
/dev/block/bootdevice/by-name/LTALabel 12016       1168      10524  10% /lta-label
/dev/fuse        22994780   12698312   10280084  56% /storage/emulated

ただ、toybox のバージョンが少し古いので長い filesystem に対応できずはみ出しています。*4

ということで、今回は Android 6.0 以前と Android 7.0 以降でパースを分けるという対応になりそうです。toybox のおかげで色々コマンド打てるようになって便利。

*1:https://github.com/mackerelio/mackerel-agent/blob/master/util/filesystem.go

*2:未来のことはわからない

*3:busybox は GPL2 なので Android のライセンス上含められなかったそう

*4:ここで修正されている https://github.com/landley/toybox/commit/c10638d3b16d065c1efd97ae17c1a8bf417be706

cookpad のインターンに行ってきた話

8/10 から今日まで一ヶ月間、恵比寿にあるクックパッドインターンに行っていました。忘れないうちにヒュヒュっと書きます。

インターンについて

僕が行ったインターンは技術インターンシップです。

このインターンは前半一週間と後半二週間に分かれており、前半が講義、後半が実際に業務を行うというもの。

後半は相談可能と書いてある通り割りと柔軟に期日の設定が可能で、僕は時間があったので後半を一週間伸ばして一ヶ月となっています。

参加

初めはインターンではなく一ヶ月ほど夏にアルバイトとして行こうと思っていました。

しかし、インターンも薦められて迷っていると 「昼ごはんも出るよ?」 との声。

昼ごはんが出るなら選択肢は一つしか無いですね。インターンにしておいてとても良かったと思います。

前半

前半は社員の方が講師となり、6分野についての講義を受けます。

  • 1日目は Rails や TDD。Rails は初めて書いたのですが、一日ガッツリやることで軽くは書けるようになった気がします。*1
  • 2日目は Android。せっかくなので Kotlin で実装したり Realm 入れたりしました。Kotlin, やはり DataBinding (apt) 周りが厳しい。
  • 3日目は iOS。この日は台風が来たので夕方にシュッと帰ったのですが、終わった後 @tyage とハンバーガー屋に行ったら他のインターン生もいて面白かった。
  • 4日目はサービス開発。詳しくは下にありますが、コードを書かずにプロトタイプなどの作成を行いました。普段全くしないことで刺激的だった。

  • 5日目は機械学習。TensorFlow で画像分類だけは軽くしたことがあるのですが、この講義では sklearn を使いました。 mecab で自分で教師用データをいい感じに作るのが面白かった。
  • そして最終日は JS のコンパイラのコードジェネレータ。興味はあるけど普段はなかなか行わないことで、非常に面白かったです。親切なスライドのおかげでやったことなくても案外できました。(という煽り返し)

こうしてみると盛りだくさんな内容ですが、講師の方がわかりやすく解説してくださったので楽しくこなしていくことができました。

最終日に後半に進む人が発表されます。僕は事前に希望していたとおり、インフラの部署に所属することになりました。

後半

後半は実際に業務をこなしていくというもので、配属される部署によって内容は異なります。

僕はインフラ部署で、メンターの星さんの元で色々やりました。例えば構成図書いたり、サーバー増やしたり移行したり。

自分はインフラっぽいことはしたことがなくて、せいぜい家の RasPi を ansible で管理したり GCE で一万溶かした程度なので少し不安でしたが、みなさん優しく教えてくださっていい感じに業務を進めることができました。

サーバーの管理、大規模サービスでのロードバランサやキャッシュetc構成、DBのレプリ構成などなど様々なことを知ることができましたし、最後の方には大掛かりなこともやらせていただいてとても楽しかったです。

これだけ AWS でいろいろやってる会社は少ないと思うし、興味がある人はぜひ行ってみるべきだと思う。

昼ごはん

インターンに行くきっかけとなった昼ごはんですが、さすが cookpad なだけあって(?)非常に美味しかったです。みなさん行きましょう。

詳しくは下の pocke くん*2の記事を見たら良いと思います!!!!

ゆゆ式

完璧に対応してた。

http://alice345.hatenablog.com/entry/2016/09/04/100000

その他

  • オフィス、恵比寿ガーデンプレイスにあるのだけど、恵比寿ガーデンプレイスは丘の上にあるので cookpad 社内からの景色が非常に良かった。良く窓際の人を駄目にするソファーでコード書いてました。
  • オフィスにたまにバナナが置いてあって食べれて良かった。バナナ美味しい。
  • 社内ツールがいろいろとそろっていて、環境を感じた。
    • ほぼ任意の場所で ruby が書かれていてさすがという感じ

まとめ

とにかく毎日が新鮮という感じで楽しかったです。インターン生も面白い人が沢山いたし、社員もすごい人ばっかりだった。

ruby はほとんど読んだことも書いたこともなかったし、AWS も EC2 ポチポチ立てたことがあるだけだった僕が ruby を好きになり route53 のマークを見ずに頭に浮かばせれるようになったのは完全に進捗だし、最高と言えるでしょう。ありがとうございました。

*1:実は bundle exec を初めて使った...

*2:彼はすごくて、rubyPython 書いたりしてた