Laravel Windows Serverでschtasksのアクセスが拒否されました問題
こちらのLaravelでシェルコマンドを実行する記事と関わります。
schtasks失敗の問題
Process Componentを使って、シェルコマンドを実行するコードをコントローラに書きましたが、本番機でテストしてみるところで、なんとschtasks
とのコマンドが失敗します。
環境はWindows Server, Laravel 6, SQL Server, Apache。コマンドの内容というのは、他のリモートサーバのタスクを実行するものとなります。大まかなコードは以下となります。
$response = ['status' => 0, 'msg' => ''];
$task_code = $request->query('task');
// ...
//'C:\Windows\System32\schtasks.exe /run /s \\\\xx.xxx.xxx.xx /u xxxx /p xxxx /tn';
$cmd = config('const.CMD');
// ['code_1' => 'task_a', 'code_2' => 'task_b', ]
$task = config('const.TASKS')[$task_code];
try {
$process = Process::fromShellCommandline("{$cmd} \"{$task}\"");
$process->run();
$output = $process->getOutput() ?: $process->getErrorOutput();
if ($process->isSuccessful()) {
$response['status'] = 1;
$response['msg'] = 'タスクが成功しました。';
} else {
$response['msg'] = 'タスク' . $task . 'が失敗しました。';
throw new ProcessFailedException($process);
}
} catch (\Exception $e) {
Log::error(__FILE__ . " (" . __LINE__ . ")" . PHP_EOL . $e->getMessage());
}
これでやってみると、以下のエラーでタスクが失敗します。ただ、直接コマンドラインから実行すると成功します。ちなみに、exec
関数に変えても同じくエラーで失敗します。
エラー:アクセスが拒否されました
誰がコマンドを実行しているか
関連情報を色々と検索してみると、管理者権限での実行が必要、という若干曖昧な情報がありました。確実かどうかはわかりませんが、様々なコマンドを試してみて、結論として少なくともschtasks
に関しては権限絡みの問題の可能性が高いと。
ここでよく分からないのは、Laravelの中でコマンドを実行するときに、「誰が実行しているのか」というところです。ログイン中のユーザーは既に管理者なので、もしログイン中のユーザーが実行しているのであれば、失敗しないはずです(直接コマンドラインからの実行は成功しているので)。
それで管理者権限でコマンドを実行する方法を検索して、runas
というコマンドを勧める内容がありました。
exec("echo {$pw} | runas /user:administrator \"{$cmd}\"", $output, $code);
上記のコマンドでechoのstdoutをrunas
のstdinとしてパイプしようとしていますが、残念ながら不可能の様子です。参考記事は[こちら](Why doesn't the RunAs program accept a password on the command line? | The Old New Thing)。どうやらセキュリティー事情で、runas
は必ず手動でパスワードを入力しなければなりません。つまりこのコマンドを実行するとパスワード入力が要求され、$cmd
のコマンドは絶対実行されません(検証済み)。
runas
の代替コマンドとして、psexec
というコマンドのがあるらしいです。
psexec [\\computer[,computer2[,...] | @file]][-u user [-p psswd][-n s][-r servicename][-h][-l][-s|-e][-x][-i [session]][-c executable [-f|-v]][-w directory][-d][-<priority>][-a n,n,...] cmd [arguments]
ただこちらは別途ツールをインストールしないといけないので、色々と大人の事情で面倒なことになります。なのでこちらの方法は一旦保留としました。
と結構悩んでいたところ、検索キーワードを少し変えて、'php exec access denied'とかで検索し、こちらの内容を見つけました。直接schtasks
と関わっていないですが、なんとなくこれっぽい気がしました。下記の手順通り、ApacheサービスのユーザーをSYSTEMから管理者に変更したら、エラーがなくなりました。
- サービスを開く
- Apache2.4を右クリック、プロパティを選ぶ
- ログオンタブで、ローカルシステムアカウントから、アカウントに切り替える
- アカウント情報を現在ログイン中の管理者ユーザーに設定
- Apacheサービスを再起動
Laravelの中でコマンドを実行するときに、「誰が実行しているのか」という問題の答えになるかもしれませんが、今までの状況で推測すると、デフォルトのSYSTEMユーザー(Local System Account)となっていて、SYSTEMには、なんらかの理由で権限が足りないため、「アクセスが拒否されました」、となってのではないかと。
誰かの役に立つかどうか分かりませんが、わけわからんトラップにハマって、何とか抗えて脱出した経験として記録しておきます。
以上です!
Discussion