【cron実行にも対応】PHPで絶対ホスト名を取得する方法
結論
組み込み関数のgethostname()を使いましょう。(ただしPHP5.3以上に限る)
PHPのバージョンが5.3より低い場合はphp_uname('n’)を使えばホスト名を取得できます。
https://www.php.net/manual/ja/function.gethostname.php
背景
PHPによるホスト名取得の使い道
バッチファイルなどのcron実行で起動するPHPファイルにおいて環境ごとに設定を切り替えるときに、ホスト名によって判断させると便利です。
<?php
/**
* batch.php
* 環境ごとに接続先データベースを切り替えてバッチ処理を実行する
*/
if(getenv('HOSTNAME') == "testenv") {
const DBNAME = "test_db";
elseif(getenv('HOSTNAME') == "productionenv") {
const DBNAME = "production_db";
}
//何らかのバッチ処理
$result = exectute_batch();
PHPによるホスト名取得の問題点
上記のファイルは一見うまくいきそうに見えるのですが、このファイルをcronでいざ実行しようとするとDBNAMEが未定義となり失敗します。
なぜでしょう。
実はcron実行でホスト名を取得するとき、gethostname()またはphp_uname('n’)を使わないとホスト名取得はできないのです。
ホスト名取得3パターンを実験してみました
以下のPHPファイルをブラウザアクセス(apache)、CLI実行、cron実行の3種類試してみました。
<?php
/**
* ホスト名取得
*/
error_log("gethostname(): ". gethostname(). PHP_EOL, 3, "hostname.log");
error_log("php_uname('n'): ". php_uname('n'). PHP_EOL, 3, "hostname.log");
error_log("\$_SERVER['HOSTNAME']: ". $_SERVER['HOSTNAME']. PHP_EOL, 3, "hostname.log");
error_log("getenv('HOSTNAME'): ". getenv('HOSTNAME'). PHP_EOL, 3, "hostname.log");
実行環境は以下の通り。
ubuntu 18.04.1 LTS (Bionic Beaver)
PHP 7.2.15-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Feb 8 2019 15:38:01) ( NTS )
Apache/2.4.29 (Ubuntu)
あらかじめホスト名を下記の通り設定しておきました。
$ hostname
test
$ echo $HOSTNAME
test
ブラウザアクセスでのホスト名取得の場合
apacheでwebサーバーを立てて、ブラウザからアクセスしてみました。ちゃんとホスト名は全て取れています。
$ php hostname.php
$ cat hostname.log
gethostname(): test
php_uname('n'): test
$_SERVER['HOSTNAME']: test
getenv('HOSTNAME'): test
CLI実行でのホスト名取得の場合
コマンドラインから直接phpを手動実行するパターンです。こちらも以下のようにホスト名を取得できています。
$ php hostname.php
$ cat hostname.log
gethostname(): test
php_uname('n'): test
$_SERVER['HOSTNAME']: test
getenv('HOSTNAME'): test
cron実行でのホスト名取得の場合
cronで実行したパターンです。やはりgethostname()とphp_uname('n’)はホスト名を取得できていますが、$_SERVER['HOSTNAME’]とgetenv('HOSTNAME’)はホスト名の取得ができていません。
$ crontab -l
* * * * * /usr/bin/php /tmp/hostname.php
$ cat hostname.log
gethostname(): test
php_uname('n'): test
$_SERVER['HOSTNAME']:
getenv('HOSTNAME'):
以下の記事でもあるように、これはそもそも上段2つと下段2つで参照している値が違うことが原因のようです。
WEB業界で働く暇人プログラマの日記 cronで実行時もホスト名を適切に取得する
PHPのホスト名取得の実験結果まとめ
結局万能なのはgethostname()とphp_uname('n’)のようです。PHP5.3以上ならgethostname()、PHP5.3より古いならphp_uname('n’)を利用するのが良さそうです。
gethostname() | php_uname('n’) | $SERVER['HOSTNAME’] | getenv('HOSTNAME’) | |
ブラウザ | ○ | ○ | ○ | ○ |
CLI | ○ | ○ | △※1 | △※1 |
cron | ○ | ○ | × | × |
※1 環境変数HOSTNAMEが定義されている場合は取得可能。