BitBarでMySQLサーバーの状態を常に意識する

# はじめに

皆さんはローカルのマシンで起動しているプロセスをチェックしていますか？もちろん通常のデスクトップOSで起動しているプロセスをすべて把握するなんて現実的ではありませんが、開発用のサーバープロセスがちゃんと起動しているかなどは把握しておくべきですよね？せめてMySQLくらいは起動しているか否かくらいを把握したいものです。

# ローカルで動かすMySQLサーバー

## Homebrewでインストール

私はMySQLをHomebrewでインストールしています。どうやらMySQL本家から手に入るインストーラーでインストールすると、メニューバーに起動中か否かの表示がされ、システム環境設定で起動／停止をコントロールすることができるようですね。羨ましいです。

## 状態に気が付かない

私はMySQLを自動起動にしていないせいで、システムの再起動後にMySQLのサービスを起動することが忘れることが多発します。プロセスが起動しているかどうかを把握しておらず、開発中のWebアプリがエラーを返すのでなぜかなーと探っていた末にMySQLが起動していなかったことに気がつくなんてことがしょっちゅうあります。

## 起動／停止はコマンドライン

サービスを起動していないことに気がついて起動しようとしますが、ターミナルを起動してShellが読み込まれるのを待ち、コマンドをタイプして実行します。「あ〜、起動するの忘れてた〜！」と気がついてからすでに数10秒経過しています。これはテンポが悪い。

# BitBar

どうせならメニューバーでシステムの状態を確認でき、サービスが停止していればメニューを選択して起動できると幸せになれそうです。

メニューバーと言えば、皆さんお馴染みのBitBarですよね。僕はここ最近、珍しくQiitaに記事を書いたりしています。

- [BitBarで自分の人生の残り時間を常に意識する](http://qiita.com/artifactsauce/items/1caca90e91c6ca90ebbf)
- [BitBarで自分のやるべきタスクを常に意識する](http://qiita.com/artifactsauce/items/2f933a1dbddf19ab008a)

こうなったらMySQLの状態を把握し、プロセスの起動／停止をコントロールするようなBitBarプラグインを書いてしまいましょう。

# 実装

表示するのはMySQLサーバーの状態と、プロセスの起動／停止を指示するメニュー項目です。

そんなこんなで作成したプラグインがこちらです。

```bash:mysql-status.1m.sh
#!/usr/bin/env bash
# <bitbar.title>MySQL server status</bitbar.title>
# <bitbar.version>v1.1</bitbar.version>
# <bitbar.author>Kenji Akiyama</bitbar.author>
# <bitbar.author.github>artifactsauce</bitbar.author.github>
# <bitbar.desc>Show the status of MySQL server installed by Homebrew on localhost and manage server boot with shortcut menus</bitbar.desc>
# <bitbar.image>http://i.imgur.com/Y85ENFb.png</bitbar.image>
# <bitbar.dependencies>bash,mysql</bitbar.dependencies>

set -eu

# Change here depending on your preference
MENUBAR_ICON_ENABLED=":dolphin:"
MENUBAR_ICON_DISABLED=":sleepy:"
STATUS_ITEM_COLOR="green"
DISABLED_ITEM_COLOR="#C0C0C0"

# Below is no need to change basically.
SERVER_CMD="/usr/local/bin/mysql.server"

SUBCMD_START="start"
SUBCMD_STOP="stop"
SUBCMD_RESTART="restart"
SUBCMD_RELOAD="reload"
SUBCMD_F_RELOAD="force-reload"
SUBCMD_STATUS="status"

if $SERVER_CMD $SUBCMD_STATUS | grep -Fq 'SUCCESS'; then
  IS_SERVER_RUNNING=true
  echo "$MENUBAR_ICON_ENABLED"
else
  IS_SERVER_RUNNING=false
  echo "$MENUBAR_ICON_DISABLED"
fi

# Server Status from `mysqladmin status`
if $IS_SERVER_RUNNING; then
  echo "---"
  LF=$'\\\x0A' # return code
  /usr/local/bin/mysqladmin -u root status | sed -e "s/$/  /" | sed -e "s/  / \| color=$STATUS_ITEM_COLOR $LF/g"
fi

# Server management shortcuts
echo "---"
if $IS_SERVER_RUNNING; then
  echo "Start | color=$DISABLED_ITEM_COLOR"
  echo "Stop | bash=$SERVER_CMD param1=$SUBCMD_STOP refresh=true terminal=false"
  echo "Restart | bash=$SERVER_CMD param1=$SUBCMD_RESTART refresh=true terminal=false"
  echo "Reload | bash=$SERVER_CMD param1=$SUBCMD_RELOAD refresh=true terminal=false"
  echo "Force-reload | bash=$SERVER_CMD param1=$SUBCMD_F_RELOAD refresh=true terminal=false"
else
  echo "Start | bash=$SERVER_CMD param1=$SUBCMD_START refresh=true terminal=false"
  echo "Stop | color=$DISABLED_ITEM_COLOR"
  echo "Restart | color=$DISABLED_ITEM_COLOR"
  echo "Reload | color=$DISABLED_ITEM_COLOR"
  echo "Force-reload | color=$DISABLED_ITEM_COLOR"
fi

echo "---"
echo "Refresh | refresh=true color=$DISABLED_ITEM_COLOR"
```

![](http://i.imgur.com/Y85ENFb.png)

# 解説

## 起動／停止コマンド

いつの頃からか、MySQLには `mysql.server` というサーバーの起動／停止をコントロールするためのShellスクリプトが付属しています。Homebrewでインストールした場合には `/usr/local/bin/mysql.server` にSymlinkが張られています。このスクリプトは引数に `start`, `stop`, `restart`, `reload`, `force-reload`, `status` というの文字列を取ることができます。

これをメニューから実行するためには下記のように出力されるようにします。

```
Start | bash=/usr/local/bin/mysql.server param1=start refresh=true terminal=false
```

`refresh` は実行後に表示内容を再生成するか否かを指定します。また、 `terminal` は実行時に新たなターミナル画面を起動するか否かを指定します。

さて、 `status` で出力される内容は下記のようなもので、起動／停止を把握するには十分ですが、できればもう少し情報があった方がありがたいですね。

起動時: `SUCCESS! MySQL running (22331)`  
停止時: `ERROR! MySQL is not running`  

## mysqladminでステイタスを取得

そこで `mysqladmin` コマンドを利用します。 `mysqladmin` はMySQL管理者コマンドをShellから使えるようにしたコマンドラインツールです。 `mysqladmin` で端的なサーバーの状態を表示するサブコマンドが `status` です。

```console
$ /usr/local/bin/mysqladmin -u root status
Uptime: 5  Threads: 1  Questions: 4  Slow queries: 0  Opens: 67  Flush tables: 1  Open tables: 60  Queries per second avg: 0.800
```

しかしその出力は横に長く、メニューに表示するには合いません。

## `sed` で改行コードに置換する

出力をよく見ると、KeyとValueの間は `:` と半角スペースで区切られていますが、それぞれの項目はダブルスペースで区切られています。ダブルスペースを改行に変換すれば良い感じに表示できそうです。

というわけで `sed` を使って変換してみましょう。

```console
$ /usr/local/bin/mysqladmin -u root status | sed -e "s/  /\n/g"
Uptime: 518nThreads: 1nQuestions: 22nSlow queries: 0nOpens: 67nFlush tables: 1nOpen tables: 60nQueries per second avg: 0.042
```

あ…れ？なんか `n` って文字が入っています。エスケープを重ねてもダメなようです。 `\n` では改行コードとして認識してもらえないようです。

そこでこのように書きます。

```console
$ export LF=$'\\\x0A'; /usr/local/bin/mysqladmin -u root status | sed -e "s/  /$LF/g"
Uptime: 858
Threads: 1
Questions: 46
Slow queries: 0
Opens: 67
Flush tables: 1
Open tables: 60
Queries per second avg: 0.053
```

## `sed` で行末に文字列を追加する

期待したとおりに改行して表示されたところで、文字色を変更したいと思います。文字色は例えば下記のような記法で表現します。各行の出力に対し、文字色等の指定が必要です。

```
Uptime: 858 | color=red
```

前述の `sed` の変換に組み込んでみましょう。

```console
$ export LF=$'\\\x0A'; /usr/local/bin/mysqladmin -u root status | sed -e "s/  / \| color=green $LF/g"
Uptime: 6015 | color=green
Threads: 1 | color=green
Questions: 66 | color=green
Slow queries: 0 | color=green
Opens: 67 | color=green
Flush tables: 1 | color=green
Open tables: 60 | color=green
Queries per second avg: 0.010
```

あ…れ？最後の行だけ文字色が付いていません。なるほど。行末にはダブルスペースが無いので変換されないわけですね。だったら行末にダブルスペースを付ければ良いわけですね。

ここではスッキリ書くために、 `sed` を使って書いてみましょう。

```console
$ export LF=$'\\\x0A'; /usr/local/bin/mysqladmin -u root status | sed -e "s/$/  /" | sed -e "s/  / \| color=green $LF/g"
Uptime: 6323 | color=green
Threads: 1 | color=green
Questions: 78 | color=green
Slow queries: 0 | color=green
Opens: 67 | color=green
Flush tables: 1 | color=green
Open tables: 60 | color=green
Queries per second avg: 0.012 | color=green

```

はい。期待通りに出力されました。最後に改行が入っていますが、まあメニュー上での表示に問題がないので良しとしましょう。

# Pull Request

僕にしては珍しく人の役に立ちそうなプラグインを作成した上に、なぜか公式リポジトリには似たようなものも無いようだったので、これをPull Requestに出してみました。結果的には前回を上回る速さでマージしていただきました。素晴らしいです。リポジトリを見る限り、プラグインコミュニティーはやや盛り上がってない感じがありますが、活動はそれなりに活発を保っているようです。安心しました。

# 最後に

地味なフラストレーションも解消され、承認欲求も満たされ、大変幸せです。ちなみに上述のコードは本家のリポジトリにマージされたコードを少し修正したものです。メニュー表示に問題が発見されたのですが、気になる方は `diff` でも見てみてください。もう少し修正が溜まったら再度リリースするつもりです。