我使用以下代码在后台运行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_PROTOCOL
、SERVER_NAME
和REQUEST_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
变量进行消毒。