MySQL道普請便り

第162回 mysqlクライアントの履歴を確認してみる

この記事を読むのに必要な時間:およそ 2.5 分

最近ではバッチ化や自動化等をして直接手動で作業するということは少なくなったかと思いますが,手動で作業をしている時に,どこまで何をやったのか,わからなくなってしまうことがあると思います。また,作業した内容を証跡として残したい事もあると思います。そんな場合に,便利なmysqlクライアントの履歴に関して紹介していきます。

mysqlクライアントの履歴に関して

第77回 mysqlコマンドラインクライアントの2ページめで紹介されているように,実行したコマンドはホームディレクトリの.mysql_historyに書き込まれます。

DockerのMySQLイメージを使って確認してみましょう。

$ docker-compose exec mysql bash
root@f1e1c7cd03a5:/# mysql -uroot -ppassword
mysql> exit

.mysql_historyの基本機能に関して

ログインしてexitだけ行った場合に,どのような結果になるか確認してみます。MySQLのDockerイメージではrootユーザで動いているので,rootユーザのホームディレクトリ内にある.mysql_historyを表示してみます。

root@f1e1c7cd03a5:~# cat /root/.mysql_history
_HiStOrY_V2_
exit

上記のように記憶されていることがわかります。

再度ログインをして上キーを押すと,これは以下のように表示されます。

root@f1e1c7cd03a5:~# mysql -uroot -ppassword
mysql> exit

このように,過去に打ったコマンドを逐次探していくことができます。こちらは見ていただいた通り単純なテキストファイルになっているため,以下のように末尾に「良いお年を」という文字列を入れた後で,ログイン後に上キーを押して見ると「こんにちは」が表示されます。この動作から文字列で管理されている事がわかります。

root@f1e1c7cd03a5:~# cat /root/.mysql_history
_HiStOrY_V2_
exit
良いお年を
root@f1e1c7cd03a5:~# mysql -uroot -ppassword
mysql> 良いお年を

あまりないかもしれませんが,サーバを再構築する際などに事前に保存しておくと,構築後に同様のヒストリーを使うこともできます。_HiStOrY_V2_は最初に登場するものだけが認識されるので,この文字列が履歴をたどっている時に現れるのが問題なければ,既存のデータと追加したい履歴データをマージするだけで利用することができます。

また,historyの検索をしたい場合もあると思います。その場合は,ctrl+rを押すと以下のようにbck:という表示が出て,検索することもできます。

mysql> 
bck:

試してみる前に,適当なselect文を実行して以下のようにします。

root@f1e1c7cd03a5:~# cat /root/.mysql_history
_HiStOrY_V2_
exit
こんにちは
exit
select\0401;
select\04012;
select\04013;
select\04014;
select\04015;
select\04016;
select\04017;
exit

この状態でctrl+rを押して検索モードに入り,sと打ってみると,直近該当するselect 17;というコマンドが表示されました。

mysql> select 17;
bck:s

この状態で,別の該当するコマンドを探したい場合は,さらにctrl+rを押していくと,select 16;select 15;といったように順々に検索条件に合致するコマンドを探していくことができます。使いたいSQLが見つかった場合はEnterキーを押すと検索モードから抜けて,さらにEnterキーを押すと実行ができます。

また,.mysql_historyはホームディレクトリに配置されると書きましたが,こちらを変更することもできます。MYSQL_HISTFILEという環境変数でディレクトリを指定することで任意のディレクトリに配置することができます。

今回/root/history/history_fileに置くように指定をしていきます。

root@f1e1c7cd03a5:~# mkdir /root/history
root@f1e1c7cd03a5:~# export MYSQL_HISTFILE="/root/history/history_file"

続けて,MySQLにログインしてselect 1;とselect 2;を行った後にexitします。

root@f1e1c7cd03a5:~# mysql -uroot -ppassword
mysql> select 1;
mysql> select 2;
mysql> exit

上記の結果がMYSQL_HISTFILEに指定したファイルに書き込まれているか,確認してみます。

root@f1e1c7cd03a5:~# cat /root/history/history_file
_HiStOrY_V2_
select\0401;
select\0402;
exit

このように,指定したファイルに書き込まれていることがわかります。この機能を使うと,同じmysqlクライアントから違うDBにアクセスする際に,historyを別けたい時にshellscript等を用意して,分けることで違うDB用のhistoryが紛れ込むというのを防ぐなどといった使い方ができます。

historyを保存しないようにする

historyを保存しないようにするにはいくつか方法があり,一括で保存できないようにする方法と,合致するパターンが存在する場合に保存ができないようにする方法があります。

1つは.mysql_history/dev/nullのシンボリックリンクにするという方法があります。/dev/nullはLinuxの特殊なファイルで書き込んだ文字列を全て捨てるという処理をします。

root@f1e1c7cd03a5:~# ln -s /dev/null /root/.mysql_history
ln: failed to create symbolic link '/root/.mysql_history': File exists

今の状態でシンボリックリンクを作ろうとすると,ファイルが存在するため一旦削除してから作成します。

root@f1e1c7cd03a5:~# rm /root/.mysql_history
root@f1e1c7cd03a5:~# ln -s /dev/null /root/.mysql_history

mysqlクライアントが書き込もうとしたhistoryが,/dev/nullに送られてしまい消えてしまうため,保存されないという仕組みになります。複数人で同じユーザで触る可能性がある場合などは,こうしておくと予期せず見えてしまうことが防げるでしょう。

もう1つは似たような話になってしまいますが,先の項目で指定したMYSQL_HISTFILE/dev/nullに向けてしまうという方法があります。

続いて,特定のクエリがある場合に保存ができなくする方法を紹介します。mysqlクライアントを使用する際に,--histignoreオプションを指定することで,該当のクエリが保存されないようになります。デフォルトでは"*IDENTIFIED*:*PASSWORD*"が指定されています。これは,ユーザ作成時などでパスワードを指定した場合にそれがログに残らないように設定されています。

Dockerで建てたMySQLを再起動して,MySQLにログインし直しユーザを作成した際に,同時にPASSWORDを設定してみましょう。

mysql> CREATE USER 'kk2170'@'localhost' IDENTIFIED BY 'test';

root@43cfa3e9ffe9:/# cat /root/.mysql_history
_HiStOrY_V2_
exit

確認してみたところ,履歴に残っていないことがわかりました。このデフォルトのオプションは変更することはできず,--histignoreオプションで指定したオプションはそれらに加える形で追加されるため,"*IDENTIFIED*:*PASSWORD*"を改めて設定する必要はありません。

パターンは大文字小文字を区別せずに,:区切りで登録ができます。使用できる特殊文字は2つで,?*です。*は長さ0以上の任意の文字列を指していて,?は長さ1の任意の文字を表しています。

つまり,--histignore="*"と登録すると,全ての文字列が登録されないという結果になります。

この--histignoreは,環境変数MYSQL_HISTIGNOREとしても宣言できます。同時に設定した場合は--histignoreに設定したものが使用されます。

まとめ

今回は,mysqlクライアントの履歴に関して紹介させていただきました。年末に向けてさまざまな整理整頓等されていると思いますが,手元の履歴を確認してゴミ掃除をしてみてはいかがでしょうか。

著者プロフィール

木村浩一郎(きむらこういちろう)

株式会社オプティム 技術統括本部のエンジニア。最近はミドルウェア・インフラ周りのことも少しずつ学習しています。趣味は将棋。好きな戦法は四間飛車。

Twitter:@kk2170