三流エンジニアの落書き帳

さあ、今日も未知という扉を開けてみよう

MySQL Shellのプロンプトを変えてみる

今回はタイトル通り小ネタです。

MySQL Shellは次世代のコマンドラインクライアントです。 従来のmysqlクライアントと比べるとSQL以外にPython, JavaScriptが扱える、Xプロトコルで接続するなどと様々な変化があります。 他にも色を使って少しリッチに見せたりと、開発チームもプロダクトに力を入れているように感じます。

今回はそんなMySQL Shellのプロンプトを色々変えてみたり、自分用にカスタマイズする方法を見ていこうと思います。

MySQL Shellのバージョンは8.0.20です。

f:id:koreshiki-nanno:20200519145715p:plain
デフォルトのプロンプト

デフォルトのプロンプトは上画像のようにMySQLという文字列から始まり、現在接続しているホスト名およびポート番号、SSL(SSL接続をしていれば)、カレントデータベース、入力モードが順に表示されています。

ポート番号横の+記号は現在の接続がXプロトコルを使用しているかどうかを表しています。

他のビルトインのプロンプトに変えてみる

まずは、もともと備わっているプロンプトがいくつかあるので、デフォルトからそれらのプロンプトに変えてみてみます。 これらのプロンプトの設定はjsonで書かれています。

[root@centos8-instance3:/usr/share/mysqlsh/prompt]# ll *json
-rw-r--r--. 1 root root 1245  311 22:50 prompt_16.json
-rw-r--r--. 1 root root 2137  311 22:50 prompt_256.json
-rw-r--r--. 1 root root 1622  311 22:50 prompt_256inv.json
-rw-r--r--. 1 root root 2179  311 22:50 prompt_256pl+aw.json
-rw-r--r--. 1 root root 1921  311 22:50 prompt_256pl.json
-rw-r--r--. 1 root root  183  311 22:50 prompt_classic.json
-rw-r--r--. 1 root root 2172  311 22:50 prompt_dbl_256.json
-rw-r--r--. 1 root root 2250  311 22:50 prompt_dbl_256pl+aw.json
-rw-r--r--. 1 root root 1992  311 22:50 prompt_dbl_256pl.json
-rw-r--r--. 1 root root 1205  311 22:50 prompt_nocolor.json

上記はCentOS8上での例です。rpmでインストールしているのでこれらのjsonファイルは/usr/share/mysqlsh/promptに置かれています。 Windows環境や、ソースからビルドしていたりするとこれらの配置場所は変わってきます。

ファイル名に含まれる数字はプロンプトで使える色の数を示しています。数字が含まれていないものはプロンプトに色が無いものです。 他にもinvはinvisibleの略で背景色が設定されないことを示していたり、pl,awはそれぞれPowerlineのシンボル、awesomeシンボルをプロンプトに表示します。(別途追加のインストールが必要)dblが含まれるものは下記のようにプロンプトが2行で表示されます。 デフォルトではprompt_256.jsonが使われています。

f:id:koreshiki-nanno:20200519225524p:plain
prompt_dbl_256.json

プロンプトが長くなってしまう場合は選択肢に入れてもいいと思います。

ここではデフォルトのプロンプトを変える方法を2つ紹介します。

~/.mysqlsh/prompt.jsonを設定する

例えばprompt_256inv.jsonをデフォルトのプロンプトに変更するには次のようにします。

cp /usr/share/mysqlsh/prompt/prompt_256inv.json ~/.mysqlsh/prompt.json

プロンプトは下記画像のようになります。

f:id:koreshiki-nanno:20200519172702p:plain
prompt_256inv.json

色はついていますが背景色は設定されていません。

環境変数を使う方法

もう一つの方法として環境変数を使う方法もあります。

この方法でデフォルトのプロンプトをprompt_256pl+aw.jsonに変えたい場合は次のようにします。

export MYSQLSH_PROMPT_THEME=/usr/share/mysqlsh/prompt/prompt_256pl+aw.json

プロンプトは下記画像のようになります。

f:id:koreshiki-nanno:20200519173836p:plain
prompt_256pl+aw.json

サーバーやSSLを表す鍵のアイコンなどが表示されます。

プロンプトをカスタマイズする

MySQL Shellのプロンプトはデフォルトでも十分に利用できると思いますが、自分でカスタマイズするとより愛着がわくというものです。

上述した通りプロンプトの設定はjsonファイルで書かれています。 つまりjsonファイルを書くことによって独自のプロンプトを作ることも可能です。

もちろんスクラッチから作ってもいいのですが、手っ取り早いのは上で紹介したビルトインのjsonファイルをコピーしてそこに変更を加える方法です。

ここではprompt_256.jsonをベースとしてカスタマイズしてみます。

プロンプトで本番環境と開発環境を区別する

運用作業をされている方は一度くらいは開発環境と本番環境を間違えて作業してしまったという経験があるのではないのでしょうか。 もちろん大きな作業をする前には目視での確認などは意識的に行うと思いますが、簡単な作業だとついうっかりなんてこともあると思います。

それらを避けるために、本番環境と開発環境でクライアントツールのプロンプトを変えるのは良い方法です。 例えばprompt_256.jsonには最初から本番環境に該当するホストに接続したときプロンプトを変えるといった機能が備わっています。

prompt_256.json(抜粋)

    "production" : {
      "text": " PRODUCTION ",
      "bg": "red",
      "fg": "white"
    }
  },
  "variables" : {
    "is_production": {
        "match" : {
            "pattern": "*;%host%;*",
            "value": ";%env:PRODUCTION_SERVERS%;"
        },
        "if_true" : "production",
        "if_false" : ""
    }

この設定ではPRODUCTION_SERVERSという環境変数を用意して、その変数に含まれるホストに接続したときにproductionという文字列をプロンプトに表示させます。

実際にその様子を見てみます。

f:id:koreshiki-nanno:20200519222620p:plain
本番環境及びテスト環境に接続したときの様子

接続したホスト(192.168.0.12)がPRODUCTION_SERVERSに含まれるため、プロンプトに赤背景白抜き文字でPRODUCTIONという文字列が表示されています。(上画像で赤く囲まれている部分)

そのあと別のホスト(192.168.0.10)に接続すると、このホストはPRODUCTION_SERVERSに含まれないためプロンプトにPRODUCTIONは表示されません。

このままでもいいのですがカスタマイズの練習も兼ねて、テスト環境に接続したときプロンプトにTESTという文字列が表示されるようにしてみます。

[root@centos8-instance3:/usr/share/mysqlsh/prompt]# diff my_prompt_256.json prompt_256.json 
47,52d46
<     },
<       
<     "test" : {
<       "text": " TEST ",
<       "bg": "green",
<       "fg": "white"
64,71d57
<     "is_test": {
<         "match" : {
<             "pattern": "*;%host%;*",
<             "value": ";%env:TEST_SERVERS%;"
<         },
<         "if_true" : "test",
<         "if_false" : ""
<     },
93c79
<    "classes": ["disconnected%host%", "%is_production%", "%is_test%"]
---
>    "classes": ["disconnected%host%", "%is_production%"]

TEST_SERVERSという環境変数を用意して、そこに192.168.0.10をセットします。

f:id:koreshiki-nanno:20200519224551p:plain
テスト環境に接続した様子

テスト環境(192.168.0.10)に接続するとプロンプトに緑背景白抜きの文字でTESTと表示されました。

あとは、本番環境およびテスト環境のホスト名を記載したファイルをそれぞれ用意して、それらを.bash_profileで読み込んで各環境変数にセットするような処理を書いておけば本番環境とテスト環境でプロンプトを変更することが可能になります。

もしくは次のようにしてもいいかと思います。

    "test" : {
      "text": " TEST ",
      "bg": "green",
      "fg": "white"
    }
  },
  "variables" : {
    "is_production": {
        "match" : {
            "pattern": "*;%host%;*",
            "value": ";%env:PRODUCTION_SERVERS%;"
        },
        "if_true" : "production",
        "if_false" : "test"

is_productionの設定でパターンにマッチしなければtestを設定するようにしました。 この場合、TEST_SERVERSのような追加の環境変数は必要なくなります。

もう1つこの方法の良いところは本番環境用のリストだけ用意しておけば、そこに含まれないホストは自然とテスト環境と判断されるため複数のリストを管理する必要が無いことです。(この場合は逆にテスト環境だけ設定して、それ以外を本番環境と判断するといったほうが安全です) その代わり本番環境、テスト環境以外に例えばステージング環境用のプロンプトを用意したい場合にはこの方法は使えません。

プロンプトにMySQLバージョンを含める

もう少しカスタマイズになれるために今度は接続しているMySQLのバージョンをプロンプトに含めるようにしてみます。

そのために簡単に設定ファイルがどのような構成になっているのか見ていきます。

プロンプトの設定ファイルは次のような構成をしています。

{
  "segments" : [
    { "classes": ["class1", "class2", ...],
      "text": text,
      "fg": color,
      "bg": color,
      "bold": bool,
      "underline": bool,
      "separator": "char",
      "min_width": integer,
      "weight": integer,
      "shrink": "none"|"truncate_on_dot"|"ellipsize"
  ],
  "classes" : {
    "class1": {
      "text": text,
      "fg": color,
      "bg": color,
      "bold": bool,
      "underline": bool,
      "separator": "char",
      "min_width": integer
    }
  },
  "variables" : {
    "variable": variable_def
  },
  "prompt" : {
    "text": "> ",
    "cont_text": "-> ",
    "fg": "32"
  },
  "symbols" : {
    "ellipsis": "...",
    "separator": "-",
    "separator2": "-"
  }
}

segments : プロンプトにどの順番でどの要素を表示するかを制御します。

classes : segmentsに含まれる要素を定義します。

variables : 設定ファイル中で使うことのできる変数を定義します。

prompt : プロンプトの最後に表示される文字を定義します。

symbols : 区切り文字やshrinkされたときに表記する文字列を定義します。

変数には予めMySQL Shellで定義されている変数(%schema%など)のほかに接続したMySQLサーバのシステム変数(SHOW [GLOBAL | SESSION] VARIABLESの値)やステータス変数(SHOW [GLOBAL | SESSION ] STATUSの値)を利用することもできます。

今回はシステム変数であるversionを使いたいのでversionというクラスを次のように定義します。

"version" : {
  "text": " %sysvar:version%"
}

%sysvar:VARNAME%SELECT @@global.VARNAMEの値を使うことを意味します。 すなわち、上記はMySQLのバージョンを宣言していることになります。

一方で%status:VARNAME%SELECT VARIABLE_VALUE FROM performance_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = 'VARNAME'の値を使うことを意味します。

また、それぞれsessvar, sessstatusとするとグローバル値ではなくセッション値を使うようになります。

設定ファイル内で使える変数などの詳細は/usr/share/mysqlsh/prompt/README.promptを参照してみてください。

あとは、segmentsセクションにversionを含めるようにして上がればOKです。 今回はMySQLという文字列の後ろにバージョンを表記したいので次のように書きます。

:
{
  "text": " My",
  "bg": 254,
  "fg": 23
},
{
  "text": "SQL ",
  "bg": 254,
  "fg": 166
},
{
  "classes": ["version"],
  "bg": 254,
  "fg": 0
},
:

bg, fgはそれぞれ背景色、文字色を指定します。色の指定方法はredなどの名前による方法、0~255のインデックスで指定する方法、rgb値で指定する方法があります。

こうするとプロンプトは次のようになります。(プロンプトが長くなったのでprompt_dbl_256.jsonをベースにしています)

f:id:koreshiki-nanno:20200520015346p:plain
プロンプトにバージョンを含めている様子

ちゃんとプロンプトにMySQLのバージョンが含まれていますね。

まとめ

というわけで、今回はMySQL Shellのプロンプトをいろいろと変えてみました。

やっぱり自分で設定すると愛着って湧きますよね :)

ぜひ自分のお気に入りのプロンプトをカスタマイズしてみてください!!

f:id:koreshiki-nanno:20200520024635p:plain
最終的にこんな感じで落ち着きました ; )