概要
dockerで開発しているときに、リモートにあるサーバーに入っているmysqlの中身を参照したくなりました。
というわけでトンネル接続をしてmysqlコマンドを流そうと思い立ち、実際に実行…するまでにハマったポイントについての解説と実行の記事です。
また、実際に行った事柄について時系列順で述べているので寄り道が発生しています。
同じように引っかかった人は必ず最後のまとめまで見てから実行してください。
環境
ローカルサーバー
Ubuntu 20.04
リモートサーバー
CentOS
Mysql 5.6.34
やろうとしたこと
$ ssh -L 9999:localhost:3306 -p xxxx user@remote.server
# 別のシェルにて
$ mysql -P 9999 -u user -p
これを行ったときに以下のエラーが出ます。
Could not create unix socket lock file /var/run/mysqld/mysqld.sock.lock
とりあえず
上記エラーで検索を行ったところ、以下の記事がヒット
https://qiita.com/fukamiiiiinmin/items/a358498b8adb37a7c251
mysqlを入れて、sockファイルがきちんと生成できるように権限を整えてあげればいいらしい。
というわけで
mysqlをUbuntuにインストールし、/var/run/mysqld
ディレクトリを生成して権限をmysql:mysql
に修正。
サービスからmysqlを起動したところ、無事にローカルにmysqlを起動することができました。
というわけで、エラーがなくなったはずのmysqlに再び接続です。
$ ssh -L 9999:localhost:3306 -p xxxx user@remote.server
# 別のシェルにて
$ mysql -P 9999 -u user -p
> password:
> ERROR 1045 (28000): Access denied for user 'user'@'localhost' (using password: YES)
やっぱり接続できない……
もしかしてMysqlが動いているように見せかけてエラーしてる?
とりあえず、ローカルのMysqlに接続できるか確認してみました。
$ mysql -u root -p
...
mysql>
正常成功しています。
念のためローカルのstatusを見てみましょう。
mysql> status
--------------
mysql Ver 8.0.27-0ubuntu0.20.04.1 for Linux on x86_64 ((Ubuntu))
Connection id: 10
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 8.0.27-0ubuntu0.20.04.1 (Ubuntu)
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8mb4
Conn. characterset: utf8mb4
UNIX socket: /var/run/mysqld/mysqld.sock
Binary data as: Hexadecimal
Uptime: 8 sec
Threads: 2 Questions: 9 Slow queries: 0 Opens: 117 Flush tables: 3 Open tables: 36 Queries per second avg: 1.125
--------------
あれ?ステータスの中にポート番号が入ってない…????
そもそもConnectionがおかしいぞ?
そもそもやろうとしているのはソケット通信ではなくTCP/IP接続のはず……
というわけで、再び検索。
「MySQL ポート番号が効かない」で検索
Unix では、MySQL プログラムはホスト名 localhost を、ほかのネットワークベースのプログラムと比較して想定されるのとはおそらく異なる、特別な方法で扱います。localhost への接続で、MySQL プログラムは Unix ソケットファイルを使用してローカルサーバーに接続しようとします。これは、ポート番号を指定するために --port または -P オプションが与えられた場合にも生じます。クライアントがローカルサーバーに TCP/IP 接続を行うことを保証するには、--host または -h を使用して、ホスト名の値 127.0.0.1、またはローカルサーバーの IP アドレスまたは名前を指定します。--protocol=TCP オプションを使用して、localhost に対しても、接続プロトコルを明示的に指定することもできます。
つまり、-h localhost
(つまりデフォルトでホストを指定していない状態)はUnixソケットファイルを使用して強制的にローカルに行ってしまう。と。
結論から言うと
IPアドレスの場所にlocalhostを指定すると勝手にsocket通信が展開されてしまうため、そもそもポート指定オプションが効かない=ローカルのmysqlにがんばって接続しようとしていた。のが問題だったようです。
正しい例は以下
$ ssh -L 9999:127.0.0.1:3306 -p xxxx user@remote.server
# 別のシェルにて
$ mysql -h 127.0.0.1 -P 9999 -u user -p
password:
mysql>
当然ですがローカル環境にMySQLは必要ありません。
間違えてインストールしてしまった場合はしっかりアンインストールするか、そっとサービスストップしてあげましょう。
お粗末様でした。