ぐるっとぐりっど

日曜プログラマがいろいろ試してみたことを、後の自分のためにまとめておく場所

毎日コミット緑化計画とTILリポジトリ

なんか、時代遅れ感もするふたつのテーマですが

毎日githubに草を生やすという運動があります。一応補足しておくと、githubで管理しているリポジトリにコミットしたりissue書いたりといったcontributionをすると、githubのユーザプロファイルの活動記録が緑色になるので、草生やすといったり、緑化といったりします。(ingressじゃないんで、水没はしない)

私もさいきん、エンジニアリング的なことがご無沙汰になってきた気がしていて、危機感を覚えたので6月末から緑化しはじめました。

はじめてから3週間たったけど、飲み会で深夜まで飲んでた日をのぞいて、一応毎日なにかしらしています。

本来であれば、毎日コードを書くことで

  • ゲームとかそういった誘惑にまけずに、30分でもいいからソフトウェアエンジニアとして活動できる
  • 塵もつもればなんとやら、な感じで、成果が出る
  • 毎日コードに触れていると、頭のコンテキストスイッチの負担が小さくなりアイディアが生まれやすい

といったメリットがあるらしいです。

ただ、実際習慣化するまでは非常にきつい。どうしても昼間の仕事中はgithubやらの開発はできないので、無理がでてきてしまいます。

そうすると、本来であれば今日あそこまでできそうだけど、やりきってしまうと明日のコミットネタがなくなってしまうので、残りは明日にしよう、とか、何もできなかったからドットファイルだけちょっと更新しとこう、とか、なんかコミットが義務的になってしまいます。少なくとも自分はそうでした。

本来は、自己研鑽というか、自身のためを目的としてやっていたはずなのに、コミットすること自体が目的となるようなマインドでは本末転倒というものです。

正直そんなマインドでやっても苦痛なだけなので、もうやめようと、毎日緑化をはじめて2週間ぐらいで思ったのですが、そこで出会ったのがtilリポジトリです(なんか青汁の宣伝番組みたいなノリだな)。

tilリポジトリは、2016年の頭ぐらいから話題になっていたらしく、「Today I Learned」の略で、今日自分が学んだことをまとめる自習リポジトリらしいです。

githubはorg-modeだったり、markdownで書いたものが、ページ上で見れるし、シンタックスハイライトもあるので、コードスニペットをまとめておくのにも便利。別にqiitaに書いてもいいんだろうけれど、qiitaには本の感想は書きづらいし、なによりポエムばかりだと自分が逆の立場で見たらキレると思うので、qiitaにポエムは書きたくない。フィードバックがほしければはやりのプラットフォームにのっかっといたほうがよい面もあるのですが。

このtilリポジトリの大きな特徴は、学んだことをまとめるので、INPUTもコミットネタになるということです。よく毎日緑化の文脈で言われる、アウトプット偏重になってしまい、インプットがおろそかになってしまうので緑化はやめた、というのも防げます。

現に、最近ちょっと自身が、家でコード書きたい欲が下がり、かわりに別の趣味のほうのウェイトが上がっているので、毎日コミットが、だいたい読書記録になってます。

どうしても何もできないときは、今度読む予定の本のファイルだけ作っておくのですが、一応githubに公開しているという体面上、あまり空ファイルばっかり作るのも抵抗があり、良い歯止めになりそう。

そんなわけで、githubの1リポジトリでほそぼそとやってます。貯まったら、blogなりを自動生成できるようにするのもおもしろそうだなー。

github.com

topで負荷の高いプロセスN個を取り出す

以下の記事の通り、最近は、influxdbをはじめとするTICKスタックで、サーバのメトリクスを収集して問題ないかみている。

grugrut.hatenablog.jp

で、現在存在していないメトリクスで欲しいものは、自分でプラグインを書いてプルリク送ってみたりしてる。

github.com

裕福な人は違うかもしれないけど、一般的にVPSとかクラウド系のリソースで最初に厳しくなるのはメモリだと思う。ディスクだったりCPUが不足することはそうそうないけど、たいていメモリは50%は軽く越えてしまう。僕自身もその例に違わず、メモリが常日頃から不足する状況が続いていた。

でもろくに分析してないので、メモリが不足している原因が、1つのプロセスが食ってるのか、複数のプロセスに原因があるのかわかっていなかった。

直感的には、Jenkins(つまりはjava)プロセスがリソース食ってるのはわかってたんだけど、メモリ使用率に変動があったときに、どこに原因があるかはわからずじまいで対策が取りようになかったので、プロセスごとのCPU使用率、メモリ使用率をとってみることにした。全部取ると大変なことになってしまうので、今回はトップ5だけ取ってみる。

データの取得方法

もちろんgolangでちゃんとプラグインとして書いてもよいのだけど、面倒なので今回はtelegrafのexecプラグインを使う。execプラグインはコマンドを実行し、規定のフォーマットで標準出力に出力されたものを値として取り込むことができる。詳細は以下を見てほしい。

telegraf/README.md at master · influxdata/telegraf · GitHub

で、その形式というのが、

メトリクス名,タグ フィールド

なので、それに合わせて出力してやる必要がある。

スクリプト

topコマンドでさくっととれる。

#!/bin/bash

top -b -n 1 | tail -n +8 | head -5 | awk '{print "process,process="$12" cpu="$9}'
top -b -n 1 -o %MEM| tail -n +8 | head -5 | awk '{print "process,process="$12" mem="$10}'

topは -bオプションをつけるとバッチモードで標準出力にそのまま結果が流れる。 -nオプションはデータを取る回数。通常は無限ループするけど、-n 1としてやることで1回出力すればコマンドが終了する。その後のtailは、topコマンドのヘッダを消すため。その後のheadは、上位のプロセス5個を取り出している。

topコマンドはデフォルトだとCPU使用率の高い順に出力されるが、-oオプションにより、ソートするカラムを選ぶことができる。2つめのtopコマンドでは、-o %MEMとして、メモリ使用率の高い順にソートされるようにしている。

これをターミナルで実行すると以下のような結果になる。

$ process.sh
process,process=top cpu=12.5
process,process=systemd cpu=0.0
process,process=kthreadd cpu=0.0
process,process=ksoftirqd/0 cpu=0.0
process,process=kworker/0:+ cpu=0.0
process,process=java mem=29.1
process,process=influxd mem=8.4
process,process=node mem=3.2
process,process=php-fpm mem=3.1
process,process=php-fpm mem=2.9

あとは、telegrafの設定を変えて、execプラグインでこのシェルスクリプトを実行してやればOK。

 [[inputs.exec]]
   ## Commands array
    commands = [
      "/path/to/process.sh"
    ]
#   commands = [
#     "/tmp/test.sh",
#     "/usr/bin/mycollector --foo=bar",
#     "/tmp/collect_*.sh"
#   ]
#
#   ## Timeout for each command to complete.
   timeout = "5s"
#
#   ## measurement name suffix (for separating different commands)
#    name_suffix = "_mycollector"
#
#   ## Data format to consume.
#   ## Each data format has it's own unique set of configuration options, read
#   ## more about them here:
#   ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
   data_format = "influx"

このコマンドのデータフォーマットは、influx形式なので、data_formatもinfluxとしておくこと。

Chronografで見てみる

適当なタイミングでキャプチャした結果がこんな感じ。画面左側がCPU使用率、右側がメモリ使用率。そして、上側がサーバ全体、下側が上位5プロセスのもの。

f:id:grugrut:20170710002829p:plain

こうやって見ると、CPU使用率は一瞬を切り取るためか、あまり相関がないが、メモリ使用率は相関がある。はっきりわかんだね。

左側の赤色の丸は、プロセスが追加で起動したためサーバ全体のメモリ使用率が増え、右側の緑色の丸では、トップのプロセスのメモリ使用率が下がったのでサーバ全体のメモリ使用率も下がっていることがきれいにわかる。
プロセスごとのグラフは、現状それぞれの値で描いているけれど、スタックしてつみあげグラフにしてみてもおもしろそう。

上記のスクリプトは自由に使ってもらって構いませんが、既知バグがあって、同じ名前のプロセスがある場合にうまくinfluxdbに追加できないので要注意(タグがプロセス名なので、かぶってしまう)。

きれいにしてから、golangでリライトしてプラグインにしてもいいんだけど、すでにprocessesプラグインがあって名前に迷うなー。

Slackとorg-modeを連携したかった話

情報収集してますか?


これまでrssリーダ使ってたのも未読がたまってしまい鬱陶しかったので、rssをslackに移行するだけの個人Slackに今は切り替えてます。
ただ、rssのころもそうでしたが、後でよむ的操作と、保存しておきたい操作が、slackの場合難しいです。個人Slackなんだから、pinでもなんでもすりゃいいんだけど、再集約は別の場所にしたい。無料版だとslack、メッセージ数に制限があるしね。

iftttとzapier

というわけで、スターをつけたメッセージに対し、なにかしらしたかった。

そういう用途であれば、iftttとzapierあたりがあげられます。気にはなってたけど、これまで使ったことなく、必要性を感じることもこれまでなかったのですが、遂に使うことに。

で、結論ですが、zapierを使うことにしました。理由は明快で、スターをつけたメッセージをトリガーとすることが、iftttではできなかった。iftttは何らかのトリガーでslackに投稿することはできても、slackをトリガーとすることは現状できなかったのです。
あと、MicrosoftもFlowとかいうのを最近出したようですが、これもslackをトリガーとすることはできないらしい。
zapierの懸念としては、無料プランだと、月100回までしかタスクを実行できないらしい。せっかく作成したばかりだけど大丈夫かな?

スターをつけたメッセージをトリガーにする

というわけでzapierであります。

zapierではこういった処理のことをzapと呼んでいて、「Make a zap」ボタンで簡単に作ることができます。試しにSlackでスターをつけたメッセージを、後で読むサービスのPocketに投入する、というのを作ってみたら、ポチポチするだけで簡単に作れてしまいました。超簡単。

f:id:grugrut:20170625094352p:plain

org-modeとの連携

さて、前置きがかなり長くなりましたが、org-modeとの連携です。私は、org-modeで使っているorgファイルを、DropboxスマホやPC群で共有しています。
zapierのインテグレーションを見ていると、Dropboxがあり、インテグレーションの動作に「Append Text File」というのがあったので、これでできるのでは? とやってみることにしました。
設定はこんな感じ。

f:id:grugrut:20170625094252p:plain

結果

f:id:grugrut:20170625095011p:plain

まあ、設定画面にそんなこと書いてあったので、嫌な予感はしてたのですが、勝手に拡張子.txtを追加されてしまいました。.orgって拡張子自分でつけてるのに。
ただ中身を見てみると
f:id:grugrut:20170625095801p:plain
という感じで、ちゃんと複数行にわたって追記がされているので良いかんじ。

拡張子を変える方法があればもっとよくなるのに、この悲しみはどこに伝えるのがよいのだろうか。

そろそろWSLメインで開発できるかと思ったけど、まだまだ辛さが残る

ポエムです。

来る2017/4/11にWindows10のCreators Updateがきて、WSL(Windows Subsystem for Linux/BoW/BoUoW/Bash on Ubuntu on Windows)も色々と強化されました。
で、これまでmsys2でemacsだったりnodejsなり動かしてたのだけども、ちょくちょくWindowsの世界に乗り込んでいかねばならないせいで、いろいろとつらみが高まってたので、これを機に開発はWSLに全部投げれないかなと試しに数日使ってみました。

おとなしくmacなりlinuxなりにすればいいじゃないって? ゲーム(steam)もしたいじゃない。

辛さ

emacs

WSLにはXサーバはないので、GUIemacsを使うには、何とかする必要がありました。自分はxmingを使ってます。タスクバーのアイコンがxmingのそれになってしまう以外は、特に不満はなし。
フォントがなんか小さくなってしまう場合は、xmingの起動オプションに-dpi 100をつけてやればよいみたい。

辛さとしては、emacs &で起動してinit.elを読んでる間に、Bashの操作をすると、emacsを巻き込んでBashが落ちる。
Bashemacs両方にstraceしてみた感じだと、Bash側でシステムコールに失敗してるっぽいのだけど、細かい原因は不明。

phantomjs

なんかスクリーンが見つからない的なエラーをはいて落ちる。そもそもphantomjs自体使ったことなくて、たまたまcontributeしようとしたプロジェクトがテストに使ってたのを見よう見まねで動かしただけなので環境構築ミスなだけかも。

Electron

こちらも起動すると、xmingの画面が表示されるもクラッシュしてしまう。issueとしては上がってるぽいので今後に期待。
ちなみに、msys2上でnpm installしたelectronは動いて、WSLで改めてnpm installしてみたらダメだった。Windowsとのシームレスな運用ができるってことですねニッコリ

2017.9.8追記

ビルド16275で、electronが動作するように改善されました。

grugrut.hatenablog.jp

ありがたみ

つらみだけだとアレなんで、ありがたみも

プロセスの扱い

msys2だと、Windowsに入れたGoを起動すると、psしても見ることができず、わざわざタスクマネージャから殺す必要があったのに対して、WSLだとpsできちんと見える(ような気がする)。

ホームディレクト

WSLはファイルシステムが独立してるので、Windowsから変更するとファイルが壊れてしまうらしい。
ところがどっこい、vipwでホームディレクトリを/mnt/c配下の適当なフォルダをホームディレクトリにして、WindowsからもWSLからも変更できることが確認できた。
さすがに/etcとかは無理だけど、その辺メモ帳で変更したい要件などないから問題なし

まとめ

現時点ではつらみが多いけど、議論も開発も活発だと思うので、切り捨てるには時期尚早

ELKスタックの後継なるか、influxdbのTICKスタックをさわってみた

結論から言ってしまうと、ならない。
というかそもそもELKスタックか目指してるものとは別物でしょ。どちらかと言えば、re:dashとELKスタックを比べるべき。なのでここからはTICKスタック単体の話です。

まだ半日ぐらいしかいじってないので、感想は後々変わるかも

TICKスタックとは

時系列データベースのinfluxdbでお馴染みの、influxが出しているログを収集して活用するための一連の製品群とその構成。
Telegraf、InfluxDB、Chronograf、Kapacitorからなり、それぞれ以下の役割を担っている。

  • Telegraf
    • InfruxDBをはじめとする時系列DBへの挿入に特化したコレクタ。InfluxDBだけでなく、PrometheusとかGraphiteとか、もろもろのものにつっこめるようになってるらしい。CPU使用率等のシステムリソースを収集できるように初期設定されていて、設定を有効化するだけで、InfluxDBにつっこめる。
  • InfluxDB
    • 時系列DB。RESTでデータを簡単につっこめて、SQLライクな構文でデータを取得できる。
  • Chronograf
    • 収集したデータを可視化するためのWebダッシュボードを提供する。以前は、InfluxDBのデータの可視化はGrafanaが担当してたと思うけど、自前でもいつのまにか作ってたのね。見た目はGrafanaにかなり似ていて、折れ線グラフしか表示できないところもかわらない。Kibanaみたいに柔軟な表示ができればもっと嬉しいのだけども。
  • Kapacitor
    • 収集したデータに関して、監視し、トリガーでアラートを出せるらしい。TICKスタックさわってみたといいつつ、これは特に触ってない。

https://www.influxdata.com/products/open-source/

目的

もともとVPS一台運用だったので、たいした監視は必要なかったんだけど、リソースに余裕があるかは把握しておきたかった。ただ、一時期ELKスタック(正確には、fluentdを使ってたのでEFKスタック)も使ってたけど、どうしてもElasticsearchがメモリをバカ食いするせいで、1台運用には荷が重すぎて、muninを使ってた。ただ、muninは今は表示できても、複雑な計算は苦手なので、もうちょっとパワーのあるやつが欲しかった。

最近だと、re:dashあたりがはやってて、「re:dashは軽量なので、AWSのmicroインスタンスでもいけるよ」、と聞いていたので期待してたのだけど、さすがに他の機能ももたせたサーバで動かすのには苦しい(1Gぐらいはメモリをどうしても食ってしまう。VPSだとメモリがいちばんコストに響いてくるので、1Gはきつい)ということもあり、もうちょっとシャレオツかつ軽量のもので、リソースを可視化できるようにしたかった。

インストール

https://portal.influxdata.com/downloads
を参照のこと。各OSごとにインストール方法が記載されてる。

自分の環境はCentOSだったので、たとえば

# yum install https://dl.influxdata.com/telegraf/releases/telegraf-1.2.1.x86_64.rpm
# service telegraf start

などとするだけだった。

CentOSの場合は、/etc/telegraf/telegraf.confにTelegrafの設定ファイルができるので、必要に応じてコメントを解除

# [[inputs.nginx]]                       ← コメント解除でnginx情報の収集有効化
#   ## An array of Nginx stub_status URI to gather stats.
#   urls = ["http://localhost/status"]   ← nginxのステータスページのURLに変更

とするだけで簡単に収集することができた。また、CPU使用率のような一般的なものは自動で収集してくれる。

そして、収集後、Chronografにアクセスすると、こんな感じでおしゃれにグラフ表示してくれる。

f:id:grugrut:20170429224611p:plain

InfluxDBなんで、期間内の最大値とか平均値とか、微分とかいろいろ出してくれるはずだけど、そこまではまだ手を出していない。
TICKスタックは、golangで書かれていて、プラグインも作りやすそうなんで、せっかくだからなんか作ってみたい。

さわってみて

クエリをWebで簡単に構築できて、自分のダッシュボードを作れるというところがよい。なにより軽量(現時点では、300Mバイトぐらいしか消費していない)のがよい。本当はKibanaのようにGeoIPを使って、地図で表現できたりするともっと良いのだけども。。

これまで、InfluxDBは数値データを格納するためのデータベースと誤解してたけど、どうやらテキストデータも入れれて検索もできるらしいので、そちらも今後収集してみたい。(以前使ったときは0.7.0ぐらいだったので、いろいろと進化しててびっくり。Webインタフェースも最近なくなってしまったみたいだし)

keyfreq.elでEmacsのキーバインドを効率良く使えているか振り返る

はじめに

人の.emacs.elを読んでたり、パッケージを漁ってたりすると、これいいじゃんって設定やイケてるキーバインドがいろいろと出てきます。そうするとやはりマネするというか自分のにも取り込みたくなるのが人情というものですが、はたして設定したっきりになってないでしょうか。

keyfreqは、emacsキーバインドの利用状況を記録して振り返ることができます。
(といいつつ、実際のところはコマンドの実行状況ですが)

github.com

MELPAに登録されているので、

M-x package-install keyfreq

するだけで簡単に導入可能

使いかた

上記レポジトリに書いてある通りですが、

(require 'keyfreq)
(keyfreq-mode 1)
(keyfreq-autosave-mode 1)

するだけ。

で、普通に使っていて、気になったときに

M-x keyfreq-show

すると、以下の感じで使ったキーバインドの統計情報(というか集計情報に近いかも)が表示されます。

f:id:grugrut:20170412173925p:plain

自分の場合、next-line使いすぎなので、C-vとか、ちゃんと使おうよ、って思える結果に。

あと、avyせっかく導入してみたのに、全く使ってないことがわかってしまった。

キーバインドを設定したいけど、かぶってて、、、という場合なんかにも、「でも実際のところ使ってないじゃん」というのがわかる、あるいは毎度毎度M-xしてるのであれば、キーバインド設定してもよかない?というのがわかるので、非常におもしろいパッケージだと思います。

問題点

BUGとしてissueにも登録されてますが、複数のemacsを起動したときにファイルロックが競合してうまく動かない(記録できないだけで実害は無いがロックかかってるよってメッセージがうっとうしい)のが難点。emacsclientで複数の場合にどうなのかは不明。

Jenkinsでgo言語のプロジェクトをCIする方法を調査した

はじめに

Golangをちまちまプライベートで触っていて、バックエンドサーバを試しにgolangで書いてみてるんだけど、Jenkinsのpipelineでgoを扱う方法が、調査しても断片的にしか出てこなかったので、本腰を入れて調査してみた。
pipelineでなければ、もっと簡単そうだけど、BlueOceanも1.0リリースされたしね。

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】

対象

ソースコードはこちら

github.com

単なる足し算を実装しただけの簡易なもの。
しかも明らかにミスってる(もちろんわざと)

func Sum(a int, b int) int {
	return a + a
}

これをJenkinsでTestしてみる。

事前準備

プラグインの導入、初期設定

Go pluginを導入しておく

Go Plugin - Jenkins - Jenkins Wiki

次にプラグインの設定をする。
日本語メニューの場合、「Jenkinsの設定」→「Global Tool Configuration」にGoの設定があるはず。(http://JenkinsのURL/configureTools/ にアクセスしてもよい)

インストール済Goというのに適当な名前(ここではGo1.8とした)をつけて、必要なGoのバージョンを設定しておく。これは必須ではないが、これをやっておくと、Jenkins専用のGoを設定しておくことができる。CentOSのepelリポジトリが1.6までしかなくて、depが使えなかったので、このやりかたで導入した。

f:id:grugrut:20170410195400p:plain

Jenkinsfileを書く

pipelineは、Jenkins上で書くこともできるけど、ファイルとして切り出して管理することもできる。バージョン管理もできるし、そちらの方が推されてるはず。

というわけで、Jenkinsfileをごりごり書いた。

書いてみたのがこんな

node {
    def root = tool name: 'Go1.8', type: 'go'
    ws("${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_ID}/src/github.com/grugrut/golang-ci-jenkins-pipeline") {
        withEnv(["GOROOT=${root}", "GOPATH=${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_ID}/", "PATH+GO=${root}/bin"]) {
            env.PATH="${GOPATH}/bin:$PATH"
            
            stage 'Checkout'
        
            git url: 'https://github.com/grugrut/golang-ci-jenkins-pipeline.git'
        
            stage 'preTest'
            sh 'go version'
            sh 'go get -u github.com/golang/dep/...'
            sh 'dep init'
            
            stage 'Test'
            sh 'go vet'
            sh 'go test -cover'
            
            stage 'Build'
            sh 'go build .'
            
            stage 'Deploy'
            // Do nothing.
        }
    }
}

重要(というか自分が詰まった)なのが前半部分。

    def root = tool name: 'Go1.8', type: 'go'

必要なバージョンのGoを利用するための設定がこちら。
nameのところに先程のプラグイン設定で名付けたものを入れる。
はじめに利用するときに、goが自動でダウンロードされるので、始めの一回はそこそこ時間がかかるけど、次からはすぐに使える。ちなみに、このGoのインストール先は、${JENKINS_HOME}/tools/org.jenkinsci.plugins.golang.GolangInstallation/Go1.8/
となっているようだ(最後のGo1.8は自分がつけた名前)。

    ws("${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_ID}/src/github.com/grugrut/golang-ci-jenkins-pipeline") {
        withEnv(["GOROOT=${root}", "GOPATH=${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_ID}/", "PATH+GO=${root}/bin"]) {
            env.PATH="${GOPATH}/bin:$PATH"

Goに入ってはGoに従えの格言の通り、Golangらしいファイル配置になるように設定している。
1行目のwsは、カレントディレクトリを設定している。普通は${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_ID}/が、カレントディレクトリになるところを、src配下に配置するようにしている。詳細は以下のページで。

Goコードの書き方 - The Go Programming Language

次に2行目は、GOROOTとGOPATHの二つの環境変数を設定している。PATH+GOで、goのバイナリの箇所を設定しているらしいけど、詳しいドキュメントが見付からず、ここは見様見真似でやってる。
GOPATH配下のbinもPATHに含めたかったのだけど、withEnvでやろうとすると、(おそらく)Jenkinsとしての変数展開と、shellの変数展開が競合してうまくいかなかったので、3行目に別途いれてる。


あとは、ソースコードの通り、チェックアウトして、depをインストールした上で、依存関係を解決、その後go vet, go testと来て、とおればbuildしておしまい。(とはいえtestでこけるのでbuildまで行かないのだけど)

結果

f:id:grugrut:20170410201344p:plain

こんな感じで、testにこけてることが確認できた。

なんとなく動いてる気はするけど、もっと効率の良いやりかたがありそうなので、ご存知の方いたら教えてください!!