【AWS CLI】PHPのexec();を使うとAWS CLIのcredentialsがnot foundになるときの対処方法

状況

PHPの関数exec();で --profile を使用したACLコマンドを実行すると
The config profile (profile_name) could not be found
つまり、credentials がないよ!って怒られる。
さらに、第三引数のコマンドのステータスは255が出力される(エラー)

<?php

// コマンドを変数に格納
$cmd = 'aws s3 ls s3://path/ --profile profile_name 2>&1';

// コマンドとして実行
exec($cmd, $output, $res);

// 取得結果を出力
var_dump($output);
var_dump($res);

// 結果
array(2){
[0]=>string(0)""
[1]=>string(50) "The config profile (profile_name) could not be found"
}

int(255) // $res の取得結果

しかし、コマンドラインから --profile を使用したACLコマンドを実行すると成功する。

# s3の適当なディレクトリで一覧を出力させる
$ aws s3 ls s3://path/ --profile profile_name 2>&1

# 結果例
PRE dir/
2018-09-26 12:00:00 file.txt

原因

ログインユーザとPHPの実行ユーザーが違っていた。
PHPでサーバーの環境変数を確認してみる。

<?php

// 環境変数を取得
exec('printenv', $output, $res);

// 取得結果を出力
var_dump($output);

// 結果
array(1){
[0]=>string(9)"USER=root"
}

USERという環境変数がrootになっていてログインユーザーのホームディレクトリ直下のcredentialsが読み取れていないことがわかった。

当然、コマンドラインで$ whoami を実行すると、しっかりと適切なログインユーザーが出力される。

要注意なのがコマンドラインで$ printenv を実行するとUSERは適切なログインユーザーになっているところ。
このせいで原因究明が遅れます。

# ログインユーザーの確認
$ whoami

# 結果
login_user_name

# 環境変数の確認
$ printenv

# 結果
USER=login_user_name

解決策

アパッチを起動するときに環境変数を読み込んでしまっていたことが原因でした。具体的には

# アパッチの起動
$ /etc/init.d/httpd start

を使用すると環境変数を読み込んでしまう。そこで

# アパッチの起動
$ service httpd start

を使用したら環境変数を読み込まなくなり、exec();でもcredentialsを読み取ることができました。
$ /etc/init.d/httpd start と $ service httpd start にこんな違いがあるとは思わなかった。アパッチの起動方法の違いについては↓のサイトに詳しく書いてありました。

まとめ

アパッチを起動するときは $ service を使おう。

最後まで読んで下さりありがとうございます! サポートして頂けましたら非常に励みになります。 頂いたものは全て制作費にさせて頂きます。