明滅するプログラマの思索

WEBエンジニアとして勤務している一介の男が、日々気づいたことをまとめるブログです

Apache ユーザに別のユーザとして処理を実行させる

Apacheで立てた Web サーバにリクエストを送り、それをトリガとしてサーバ上で操作を行う場合、その実行ユーザはデフォルトでは apache ユーザとなります。
これだと、そのファイルのユーザ・権限によっては、アクセス権がなく実行に失敗してしまうことが考えられます。
もちろんアクセス権を事前に変更しておき、apache ユーザでも処理を行うことができるようにする、というのも1つの方法ではありますが、そういった処理をしたくない場合もあります。
そういった場合、linux なら sudo コマンドを利用して、別のユーザとして処理を実行することができます。

ソフトウェア バージョン
CentOS 7.3
PHP 5.6

apache ユーザで /var/log/messages を参照する

ここでは例として、apache ユーザがアクセス権の無い /var/log/messages ファイルを参照するスクリプトを書いてみます。

<?php
$messages_path = '/var/log/messages';
exec(sprintf("tail %s", $messages_path), $output);
foreach ($output as $str) {
    echo $str . "\n";
}

とりあえずこれだけ。
exec() 関数を利用して、 /var/log/messages を tail コマンドで開こうとしています。
実行すると tail: `/var/log/messages' を 読み込み用に開くことが出来ません: 許可がありません というエラーが発生します。
アクセス権がないことがわかります。

visudo で権限の設定をする

まずは、apache ユーザが sudo を利用できるようにしなければなりません。
そのための設定が visudo コマンドで行うことができます。
※root ユーザで行う必要があります

visudo

上記のコマンドでは、実際は /etc/sudoers というファイルを開いているのですが、その中身を編集します。
今回は apache ユーザに、root ユーザが行えるすべての権限を与えてみます。

apache ALL=(root) NOPASSWD: ALL

上記の設定は、 ユーザに、どのホストどのユーザどんな権限を与えるか、をその並びの通りに記述したものです。
すなわち、
apache ユーザ に ALL(すべてのホスト) の rootユーザ の NOPASSWD: ALL(すべての権限(パスワード入力なしで)) を与える、となります。

これだけでOKです。

apache ユーザで rootユーザとしてコマンドを実行する

先ほどの PHPスクリプトを以下のように書き換えます。

<?php
$messages_path = '/var/log/messages';
exec(sprintf("sudo -u root tail %s", $messages_path), $output);
foreach ($output as $str) {
    echo $str . "\n";
}

これを実行すると今度はエラーが発生せず、/var/log/messages の中身が取り出せました。

まとめ

  1. 別のユーザで処理を行うためには sudo コマンドの -u オプションでユーザを指定して実行する
  2. ただし最初は権限がないので visudo コマンドを使って権限の設定をする