【cron実行にも対応】PHPで絶対ホスト名を取得する方法

2019年9月18日PHPPHP, テクニック

結論

組み込み関数の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が定義されている場合は取得可能。

サイト運営者 えぬたけ


都内で働くゆるふわフルスタックwebエンジニア。