在后台使用 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 变量。