使用popen在后台运行php脚本时填充$_SERVER


Populating $_SERVER when using popen to run a php script in background

我使用以下代码在后台运行php脚本email/send-emails.php

if(strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
   $phpExec = str_replace('/', '''', dirname(ini_get('extension_dir'))).''php.exe';
   if(!file_exists($phpExec))
      throw new Exception('Could not find executable: '.$phpExec);
} else {
   $phpExec = exec("which php-cli");
   if($phpExec{0} !== '/')
      $phpExec = exec("which php");
   if($phpExec{0} !== '/')
      throw new Exception('Could not find executable: '.$phpExec);
}
$exec = $phpExec.' email/send-emails.php';
$cmd = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' ? 'start /B '.$exec : $exec.' &';
pclose(popen($cmd, 'r'));

这在Windows和Linux上都能很好地工作。唯一的问题是$_SERVER在调用脚本和电子邮件脚本中填充了完全不同的值。例如,密钥SERVER_PROTOCOLSERVER_NAMEREQUEST_URI在电子邮件脚本中丢失。我想这是有道理的,因为调用脚本是通过Apache提供的,而电子邮件脚本不是(?)。

当使用popen调用php脚本时,是否有方法填充$_SERVER的缺失值?

最简单的方法是对文件发出HTTP请求,而不是使用popen来运行它

否则,在send-emails.php脚本中,您可以检测$_SERVER值是否丢失,并用一些合理的默认值填充它们。

考虑回退到email/send-emails.php:中的环境变量

$uri = $_SERVER['REQUEST_URI']?:getenv('REQUEST_URI');

因此,在您的主脚本中,您可以将这些值代理给工作者:

$exec = "REQUEST_URI={$_SERVER['REQUEST_URI']} ".$phpExec.' email/send-emails.php';

Windows的语法略有不同。

请注意,解决方案过于简单化,无法显示核心原则。在实际应用中,强烈建议在传递到子进程之前对$_SERVER变量进行消毒。