【问题标题】:Setting environment variables within PHP works for one user but not another在 PHP 中设置环境变量适用于一个用户,但不适用于另一个用户
【发布时间】:2020-04-20 06:56:47
【问题描述】:

一位用户一直在帮助我解决问题 (How to force a curl request in a PHP method to fail for a unit test)。他们建议使用putenv('all_proxy=localhost:5678');,这样我就可以强制curl 在单元测试中动态失败(我将http_proxy / https_proxy 更改为all_proxy,因为它执行所有协议)。

这在他们的 Ubuntu 机器上完美运行,但我无法让它在 either 我的 Windows 10 机器或 Ubuntu 机器上运行。如果我从命令提示符设置all_proxycurl 请求总是失败,因此它会在找到变量时注意到它。我稍微更改了他们的脚本,这似乎让它在 Ubuntu 上运行。

php.ini 中是否有一些设置可以控制putenv() 是否可以覆盖环境中的变量?为什么动态环境变量在他们的设置上起作用,但在我的任何一个上都不起作用 Ubuntu 而不是 Windows?

测试脚本

<?php

function search() {
  $url = 'x3m.dev';

  $curl = curl_init();
  curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_URL => $url,
  ]);
  $data = curl_exec($curl);

  if (!$data) {
    throw new Exception('An error occurred while trying to process the request.');
  }
  return $data;
}

function do_curl_request() {
  echo getenv('all_proxy') . "\n\n";
  try {
    echo search();
  }
  catch (Exception $e) {
    echo $e->getMessage();
  }
  echo "\n\n";
}

echo "========== first run without proxy\n";
do_curl_request();

putenv('all_proxy=localhost:5678');
echo "========== second run with proxy override\n";
do_curl_request();

它应该第一次工作,第二次抛出异常。在 Windows 上,如果 all_proxy 未设置为 Windows 环境变量,则两次都有效,如果设置了 all_proxy,则两次都抛出异常。

Windows(不正确)

========== first run without proxy


<html>
<head></head>
<body>.</body>
</html>

========== second run with proxy override
localhost:5678

<html>
<head></head>
<body>.</body>
</html>

Ubuntu(正确)

========== first run without proxy


<html>
<head></head>
<body>.</body>
</html>

========== second run with proxy override
localhost:5678

An error occurred while trying to process the request.

【问题讨论】:

  • localhost:5678你设置好你的本地代理了吗?
  • @Popeye 没有。关键是它应该失败,因为localhost:5678 没有这样的服务。

标签: php windows environment-variables command-line-interface


【解决方案1】:

重要的是要认识到 PHP 不会从用户环境中导入任何内容。它有自己的独立环境,是每个请求的(即它被解释器中的每个RSHUTDOWN 事件清理)。您在 php 中所做的任何事情(即putenv())都严格遵守该请求。您在 shell 中所做的操作不会影响 PHP 的环境。

putenv

设置添加到服务器环境。环境变量仅在当前请求期间存在。在请求结束时,环境将恢复到其原始状态。

【讨论】:

  • If I set all_proxy from the command prompt, the curl requests always fail, so it is taking notice of the variable when it can find it. 你的回答与我可以通过实验验证的相反。
  • 我向你保证不是。如果这样做,那将是一个巨大的安全问题。 PHP 的环境在设计上是自包含的。
  • 我可以建议您尝试设置环境变量并运行其他用户给我的脚本吗?
  • 有问题的 PHP 代码不是这里的问题。事实上,您相信您可以从命令提示符设置环境变量,并且 PHP 会神奇地导入该环境变量。 不会。您必须使用 putenv() 在 PHP 中设置该环境变量。
  • 请解释我如何通过在命令提示符下设置环境变量来改变 PHP 的行为。 (不是假设,而是当你重新运行脚本时,现实生活中的行为实际上是如何变化的)
【解决方案2】:

TL;DR

这是一个错误,已在 PHP 7.3.17 和 7.4.5(2020 年 3 月)中修复。早期版本没有已知的解决方法。


你坐得舒服吗?那我们开始吧!

  1. 此错误仅存在于 Windows 上
  2. 我创建了一个PHP bug report
  3. 这个错误之前被注意到和fixed in PHP 5,但仅适用于非线程安全版本:
    • PHP 5.4.36 非线程安全(2014 年 12 月 17 日)
    • PHP 5.5.20 非线程安全(2014 年 11 月 26 日)
    • PHP 5.6.4 非线程安全(2014 年 11 月 27 日)
  4. 该错误被标记为“部分修复”,但还是被意外关闭了,因为它从人们的视线中消失了,因此阻止了对该错误的进一步研究
  5. 有两种可能的内部调用来获取/设置环境变量:
    • SetEnvironmentVariable() / GetEnvironmentVariable()(线程安全)
    • putenv() / getenv()(非线程安全)
  6. cURL 使用 getenv() 无法看到 SetEnvironmentVariable() 所做的更改
  7. cURL bug report 现已创建

A fix for cURL 于 2020 年 2 月 12 日合并。它于 2020 年 3 月 4 日在 cURL 7.69 中发布。

关于我创建的 PHP 错误报告的注释说:

libcurl 7.69.1 已经发布,修复了这个问题,并将 用于 PHP 7.3.17 和 7.4.5 Windows 版本,所以我 关闭这张票。

【讨论】:

    猜你喜欢
    • 2019-11-22
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多