systemd の PrivateTmp 機能で /tmp/mysql.sock が見えないというお話し

今回、新たにセットアップしたサーバで CGI から MySQL への接続がうまくいかない。

環境は、

CentOS 7.4(1708)
Apache 2.4.39
MySQL 8.0.16
Perl 5.16.3
DBI 1.627
DBD::mysql 4.023

というソフトウェア構成。

Apache は systemd(init に変わる起動処理やシステム管理を行う仕組み)を使って起動している。
(systemctl start httpd.service というコマンドで起動しているというわけね)

で、この環境で、CGI から DBI/DBD 経由で MySQL にアクセスすると、

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

というエラーが発生してしまう。

しかし、/tmp/mysql.sock は存在している。権限関係も問題ない。

# ls -la /tmp/mysql*
srwxrwxrwx 1 mysql mysql 0 May 31 09:55 /tmp/mysql.sock
-rw------- 1 mysql mysql 5 May 31 09:55 /tmp/mysql.sock.lock

いやぁ、ハマったわぁ~(^^;

結局、オチから言うと、これって systemd の PrivateTmp 機能による問題で、例えばソケットの置き場所を /var/lib/mysql/mysql.sock とかにしていた人には発生しない。

どういうことかというと、今回、ソースビルドした Apache についても systemd で管理(起動等)をしているのは上に書いたとおり。
で、systemd 経由で起動したデーモン(今回は Apache)は、それぞれ独自の /tmp ディレクトリが用意される。

つまり、Apache 上で実行される CGI プログラムが見ている /tmp と、本来の /tmp ディレクトリは全然別物なので、いくら MySQL が(本来の)/tmp ディレクトリ上にソケットファイル(mysql.sock)を用意しても、CGI プログラムからは見えないのである。

結果、

DBI connect('dbname=hoge_db;host=localhost;port=3306;mysql_socket=/tmp/mysql.sock','hoge_admin',...) failed: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) at ./db_connect_test.pl line 42.

というエラーとなってしまう。
反対に、ソケットファイルの置き場を /tmp ではなく /var/lib/mysql/mysql.sock などにしていた場合は CGI からも見ることができる。これは、/tmp(/var/tmp も?)だけの問題である。

tmp は temporary の略で、/tmp ディレクトリというのは文字通り「一時ファイル」の置き場所。そのため、誰でも読み書きできるようになっており、それを専用に用意することで安全性や利便性を上げようって思想なんだろうけど、裏目に出たなあ>俺のところでは(^^;

ちなみに、じゃあ、プロセス毎の /tmp ってどこにあるの?というと、/tmp ディレクトリの下にある。

# ls -lad /tmp/systemd*
drwx------ 3 root root 4096 Apr 20  2016 /tmp/systemd-private-4ee168e88455407fa3b27bd35ffb371d-ntpd.service-1GgKhB
drwx------ 3 root root 4096 May 22 16:24 /tmp/systemd-private-bf1b49c0e6014448894be7a3091317ee-ntpd.service-5jH2a8
drwx------ 2 root root 4096 Feb  8  2016 /tmp/systemd-private-W69tS0
# ls -la /tmp/systemd-private-4ee168e88455407fa3b27bd35ffb371d-ntpd.service-1GgKhB
total 12
drwx------  3 root root 4096 Apr 20  2016 .
drwxrwxrwt 13 root root 4096 May 31 14:44 ..
drwxrwxrwt  2 root root 4096 Apr 20  2016 tmp
# ls -la /tmp/systemd-private-4ee168e88455407fa3b27bd35ffb371d-ntpd.service-1GgKhB/tmp
total 8
drwxrwxrwt 2 root root 4096 Apr 20  2016 .
drwx------ 3 root root 4096 Apr 20  2016 ..

こういう具合に、systemd が /tmp の下にそれぞれのプロセスごとに専用の /tmp を用意している。

じゃ、どうするかって話なんだけど、ソケットファイルを /tmp 以外のディレクトリに置けばいいんだけど、もう多くの CGI などで明示的に /tmp/mysql.sock を指定しているので全部直すのも大変。

とりあえず、sysytemd 経由での起動をやめる。
手動で apachectl コマンドを叩いて実行。

# systemctl stop httpd
# /usr/local/apache2/bin/apachectl start
# ps auxww|grep http
root     21911  0.0  0.2 114864  4516 ?        Ss   13:45   0:00 /usr/local/apache-2.4.39/bin/httpd -k start
apache   21912  0.0  0.1 114656  2756 ?        S    13:45   0:00 /usr/local/apache-2.4.39/bin/httpd -k start
apache   21913  0.0  0.1 401692  3328 ?        Sl   13:45   0:00 /usr/local/apache-2.4.39/bin/httpd -k start
apache   21914  0.0  0.1 401692  3324 ?        Sl   13:45   0:00 /usr/local/apache-2.4.39/bin/httpd -k start
apache   21916  0.0  0.1 401692  3324 ?        Sl   13:45   0:00 /usr/local/apache-2.4.39/bin/httpd -k start
root     22011  0.0  0.0 112708   948 pts/1    S+   13:45   0:00 grep --color=auto http

これで、CGI からも MySQL へのアクセスが可能となった。

systemd の PrivateTmp 機能を無効にする方法を調べるまでは、とりあえずこの運用とする。

トラックバック(0)

このブログ記事を参照しているブログ一覧: systemd の PrivateTmp 機能で /tmp/mysql.sock が見えないというお話し

このブログ記事に対するトラックバックURL: https://blog.netandfield.com/mt/mt-tb.cgi/5341

コメントする

このブログ記事について

このページは、shinodaが2019年5月31日 15:33に書いたブログ記事です。

ひとつ前のブログ記事は「横川「おちょこ」で旨い日本酒を楽しむ」です。

次のブログ記事は「ブログのサーバ移行中。コメント入力不可(^^;」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。


月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら