mackerel-agent に PullRequest を出した話

この記事は、Mackerel Advent Calendar 2019 - Qiitaの15日目の記事です。

事前に書こうと思ってたことができなかったので、はてなインターン中に GitHub - mackerelio/mackerel-agent: mackerel-agent is an agent program to post your hosts' metrics to mackerel.io. に出した PullRequest の話をします。

インターン中に mackerel の開発用に mac book で mackerel-agent を動かす必要があったため、mackerel-agent init -apikey "${api key}"を実行したところ、設定ファイルの作成できないというようなエラーとなりました。 詳しく調べると、設定ファイルが保存されるディレクトリが存在している場合はファイルが作られ、そうでない場合はエラーとなり実行が停止されることが分かりました。 これは、init オプションのヘルプに書いてある動きと比べておかしいと感じたので、メンターの方々とも相談して下記の PullRequest を出しました。

PullRequest の内容としては、設定ファイルの場所として指定されているパスを見て、ディレクトリが存在していない場合は新規に作成するという処理を追加するものです。 また、これを追加するのに合わせて該当の場合に対するテストも追加しました。

github.com

実際のところ、この PullRequest でどの程度便利になったのかは分かりませんが、初期化の際にディレクトリを作らなくて良くなった点は個人的によかったです。 また、今回インターン中にだったので、はてなの方に困ったらいくらでも相談できるような状況で PullRequest を出せたのでかなり恵まれていたと思います。 せっかく関わったプロジェクトなので、今後もコミットしていけたらと考えています。

本当は新しくやったことを書こうと思っていましたが、想定以上に時間がとれなかったためインターンのときのことを書くことになってしまいました。。。

アドベントカレンダーも残すところ1週間と少しになってしまいましたが、これからどんな記事が投稿されるのか楽しみです。

Go言語でWeb Assemblyに入門した

この記事は、WebAssembly Advent Calendar 2019 - Qiita の 15日目の記事です。

友人に載せられて登録してしまったので、Go言語でWasmに入門しました。

単純にチュートリアルをやるだけだとつまらないので、ちょっとだけ実用的なボタンをクリックしてメニューをトグルできるようにしました。

はじめに、github.comの通りにして作成します。

次に index.html の body タグを次の内容に変更しました。 divの子要素をWasmから操作してメニューの表示非表示を切り替えます。

<button id="menu-toggle-button">Menu</button>
<div id="menu-root"></div>

また、ついでに遷移先のHTMLファイル (about.html, links.html)も適当な内容で作成します。

その後、メニューを表示するための関数ShowMenu()と非表示にする関数HideMenu()を実装しました。

menu型の配列に入れた情報を使ってメニューのDOMを生成しています。

// リンク情報を保存するための構造体
type menu struct {
    name string
    url  string
}

var document = js.Global().Get("document")

// メニューのトグル用ボタンを取得する
func getMenuToggleButton() js.Value {
    return document.Call("getElementById", "menu-toggle-button")
}

func createElement(elementName string) js.Value {
    return document.Call("createElement", elementName)
}

func appendChild(dom js.Value, elm js.Value) js.Value {
    return dom.Call("appendChild", elm)
}

// メニューを隠す
func HideMenu(this js.Value, args []js.Value) interface{} {
    menuRoot := document.Call("getElementById", "menu-root")

    for menuRoot.Call("hasChildNodes") == js.ValueOf(true) {
        child := menuRoot.Get("lastElementChild")
        menuRoot.Call("removeChild", child)
    }

    // toggle event listener
    toggleButton := getMenuToggleButton()
    toggleButton.Call("removeEventListener", "click", js.FuncOf(HideMenu))
    toggleButton.Call("addEventListener", "click", js.FuncOf(ShowMenu))
    return nil
}

// メニューを表示する
func ShowMenu(this js.Value, args []js.Value) interface{} {
    menuList := []menu{
        {name: "home", url: "/"},
        {name: "links", url: "/links.html"},
        {name: "about", url: "/about.html"},
    }
    // make menu dom
    menuListDom := createElement("ul")
    menuListDom.Set("id", "menu-item")
    for _, e := range menuList {
        li := createElement("li")
        a := createElement("a")
        a.Set("href", e.url)
        a.Set("textContent", e.name)
        appendChild(li, a)
        appendChild(menuListDom, li)
    }
    menuRoot := document.Call("getElementById", "menu-root")
    appendChild(menuRoot, menuListDom)

    // toggle event listener
    toggleButton := getMenuToggleButton()
    toggleButton.Call("removeEventListener", "click", js.FuncOf(ShowMenu))
    toggleButton.Call("addEventListener", "click", js.FuncOf(HideMenu))
    return nil
}

次に、作成した関数をmain関数でボタンのイベントリスナーに登録します。

func main() {
    // register event
    menuToggleButton := getMenuToggleButton()
    // register call back func
    menuToggleButton.Call("addEventListener", "click", js.FuncOf(ShowMenu))

    select {}
}

ビルドは次のようにします。

GOOS=js GOARCH=wasm go build -o main.wasm

HTTPサーバは、goexecが入っていなかったのでPythonで一時的に建てました。

python -m http.server 8000

この状態で localhost:8000をブラウザで開いてボタンをクリックするとメニューの表示・非表示を切り替えられます。

f:id:tomato3713:20191215021041p:plain f:id:tomato3713:20191215021037p:plain

以上、Wasmへの入門でした。 そういえば、これを書いてるときにvimplsにsyscall/jsが見えていなかったようなんですがどうしたらいいのだろう。 明日も、Go言語とWasmらしいので何が出るのか楽しみですね。

Debianを使い始めてから約1年経った

Debianをthinkpad x1 carbon 第一世代にインストールした。 - tomato3713’s blogDebianThinkpad にインストールしてから、メインのノートPCとして使い続けています。

LinuxをメインPCとして使うようになってから感じたことを紹介します。

どういった用途で使用しているか。

実験のレポートやプログラミング、Youtube の視聴などに使用しています。レポートは、OpenOffice ではなく、LaTeX でPDF を生成しています。 プログラミングでは、Visual Studio のような統合開発環境ではなく、プラグインを入れた Vim で Go言語開発をしています。CG やゲーム用ではないので快適に暮らせています。 また、表計算や発表用のスライドについては、inkscapeGimp で画像を編集し、ブラウザ上で使用できる Office Online で作成し、適宜友人と共有ができるようにしています。 Open Office で作成してもよいのですが、Power Point でも開けることが要求されることが多いのでこのような運用になっています。

環境の整備

Go や Vim といった個別のソフトウェアのインストールスクリプトは用意していますが環境全体を整えるためのスクリプトは用意していません。開発環境の整備は好きなので、壊れたときは環境をアップデートする良い機会と考えることにしています。

良かった点

  • リッチなコマンドが用意されてる

GNU Command が標準で簡単に使用できることが最も大きな利点だと感じています。普段から、Vim でプログラミングを行っており、ターミナル上で操作をしている時間がほとんどを占めています。なので標準で多くのリッチなコマンドを使用できることは重要な要素の1つです。

  • メモリを喰わない

使用しているPCのメモリが 8GByte と mac OSWindows の場合は、メモリ不足の不安がありますが Linux であれば Docker が軽く起動できることも嬉しいです。

不自由な点

  • 動かないアプリがある

Slack については問題なく使用できますが、SkypeLinux 版がないため使えず不便です。Wineを使用して動かすこともできるかも知れませんが、今のところ頻度が高くないため Skype で通話をするときのみ Windows を持ち出してきています。たまに Linux では動かない/動作が不安定なソフトウェアがあるので注意が必要です。ですが、多くのサービスは、ブラウザで利用できるためあまり困ってはいません。

  • キー配列が正しく認識されない

これは私の端末に固有の問題だと思われますが、デスクトップにログインする前は、英字配列として認識されてしまいます。一度ログインすれば日本語配列として認識されますがシャットダウンするとリセットされてしまうのでパスワードの入力の時に混乱するときがあります。

その他

他にもいくつか問題が起こったこともありますが、Linux をデスクトップにして良かったと思っています。人に進めるかというとその人のライフライフスタイルに依る部分が大きいので、積極的には薦めませんが聞かれたら可能な範囲で相談には載るつもりです。書ききれなかったこともありますが、残りはまたの機会に書こうと思います。

リポジトリ移動用のコマンドを作った

概要

だいぶ遅れてしまいましたが、UEC Advent Calender 2019 の1日めの記事です。 今日は、日常で使用しているリポジトリ移動用に作成したシェルスクリプト関数の紹介をします。

本文

ソースコードの管理は、Go言語のフォーマットに従って次のようなディレクトリ構造としています。 私は、ghq コマンドを使用して、リポジトリの管理をしているので、ghq のルートして、${gowork}を指定しています。

# 説明に不要なディレクトリは、省略しています。
${gowork}/
  +---  bin/         # 作成したバイナリファイル  
  +---  pkg/         # Go言語の依存パッケージ
  +---  src/         # すべての言語のソースコード
          +--- github.com/${github_user}/${repository}
          +--- golang.org/
          +--- ...

この方式は、ソースコードが1箇所にまとめられて管理が楽なのですが、リポジトリ間の移動が少々不便です。 ghq look で移動することも可能ですが、その場合新規にシェルのプロセスが起動してしまうので移動を繰り返すと自分がghq look して起動したプロセス内にいるのか、最初に起動したシェルのプロセス内にいるのか分からなくなってしまいSSH等でリモートから接続している際には誤って接続を切ってしまうことがあります。

これを防ぐため、シェルのプロンプトにghq look で起動されたシェルのプロセスのときのみ GHQ のような文字列を表示する方法もありますが、私は普段次のようなシェルスクリプト関数を定義して同一のプロセス内で移動するようにしています。

# Change Repository directory なので、cr としました。
cr() {
  local dir
  dir=$(find "${GOPATH}/src/" -name ${1:-.}  -prune \
                  -o -type d -print 2> /dev/null | fzf +m) &&
  cd "$dir"
}

関数の内容的には、findコマンドで${GOPATH}/src/以下のディレクトリのリストを作り、fzf コマンドに流し込んでいるだけの簡単なものです。

ターミナルで cr 関数を呼ぶと、fzf のファジー検索が始まるので、一致したディレクトリを選択して Enter を入力すればそのディレクトリに cdしてくれます。 本当なら、.gif ディレクトリを除いて検索をしたいのですが、うまくできなかったので今はこれで妥協しています。

cr 関数の実行中のgif
cr 関数実行の様子

その他

fzfghq コマンドは、はてなサマーインターンに行ってから使うようになりました。
gif 画像を作るために、ttyrec, ttygif, ttyplay コマンドを初めて使ったのですが便利ですね。

Vim を使う理由

Vim は、明らかに設定が Visual Studio Code などの最近出てきたテキストエディタに比べて面倒くさい。 設定を弄ぶっているだけで、数時間が過ぎてしまうこともある。 コードを書くことよりも、Vim の設定を書いている時間の方が長い日もある。

Vim を使い始めたのは、Vim を使っている様子が格好良く見えたからではあるが、利点を考えてみた。

初めに、開発環境としての Vim は、総合開発環境 (IDE) と比べると貧弱で弱い。 もちろん、OniVim などのようにプラグインをもりもりに追加すればIDEと同程度の機能をつかえるようにできる。 しかし、その設定に時間をかけるよりも明らかにIDEの使い方を覚えたほうが短い学習時間で使えるようになると思う。 また、OSをまたいでつかえるかに関しても、最近の IDEテキストエディタの多くは、ブラウザ上でも使用できたり、Windows版に加えて、Linux版、Mac OS版も提供されている。 なので、この利点は少なくなってきているように思える。 キーバインドに関しては、どのツールを使っても VimEmacsキーバインドをエミュレートするプラグインは大体あるので、操作方法を差はあっても共通化できる点は利点は残っていると思う。

私は、Unix哲学にあるような「一つのことをうまくやる」ができるツールであることをツールを選ぶ上で重要視している。 それは、自分がある一瞬にできる作業は一つしかないのだから、使うツールも一つのことを確実にやれるものであってほしいという要望からきている。 なので、普段のコーディングでもファイルをまたいだ検索は、grep を使うことが多いし、gitは termianl 上から使ってしまう。 ただ、何でもテキストでいいかというと限界は感じていて、デバッガーなどはGUIで操作がしたい。 gina や docker.vim を見ていると、共通のユーザー・インターフェースとしての Vim の力を感じる。

他には、Vim はウィンドウの分割とサイズの変更、位置の移動がキーボードだけで操作できるところがいい。シェルで作業がしたくなったら:termを打てばいいし、広く見たくなったらCtrl+w + を打てばいい。いらなくなったら気軽にウィンドウを閉じられる。 起動に時間がかからないからやれることだと思う。

自分のコーディングのスキルに合わせて、VIm の設定ファイルを書き足す、有名なプラグインを使いたいから、その技術を勉強してみるのように、一緒に成長していけるところもよい。 実際、自分がGo言語をさわり始めたのは、VIm conf 2018の発表を聞いてgocodeを使いたくなったからである。

いろいろ書いたが、最終的には Vim を使うのが楽しいから Vim を使っているに尽きる。 完全にポエムになってしまった。。。

実行してて楽しいコマンドたち

w

ロードアベレージと現在ログイン中のユーザリスト、アイドル時間、実行中のコマンド等の情報が見れる。

$ w
 19:22:52 up  5:17,  1 user,  load average: 1.58, 1.55, 1.07
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
tomato   tty2     tty2             14:05    5:17m 27:51   0.00s xdotool

yes

yesをただただ出力し続けてくれる。またオプションを指定すると指定した文字列をひたすら出力する。

sl

あの有名なSL。

cowsay

牛。

top

実行中のプロセスの状態をリアルタイムに表示する。topを実行中に負荷を書けるとCPU使用率やメモリが使われていく様子がわかって楽しい。

ps -a

自分がなにかやっている裏側で大量のプロセスが動いているのがみれて面白い。

竹内郁夫著「初めての人のためのLisp[増補改訂版]を読んだ

大学の課題でSchemeを使っていらいLispをちゃんとやってみたいと考えて本書を読みました.

本書は, リストとはなにかから入り car, cdrの説明, リストがコンピュータ内でどのようなメモリ構造として保存されているのか, そしてLispの標準に的に用意されている関数の実装を考えることを通してクロージャなどの解説が鮮やかにされていました. Lispを使ってなにかを作るというよりも, Lispの概念をしっかりと理解することに重きをおいているように感じました. 他の方のレビューでも有るように多少ふざけた語り口で書かれていますが, Lispという言語の表面だけでなく低いレベルから扱っており非常に充実した本でした. Lispを書いていると再帰で書くのが自然のように思えてくるので不思議ですね.

プログラムとデータが同じ形式で表現されること(program as data)が重要であるとLisp関連の文章を読むと書かれていますが, その意味がわかったような気がしました. こんなことを言うと本を1冊読んだくらいじゃLispの真髄はわからないという人もいそうですが...

次はLispで実用的な何かを作るということをしてみたいですがどこを見れば情報が得られるのだろうか. Lisperの皆さんには作ってみました系のアウトプットを是非してほしい.

www.shoeisha.co.jp