【问题标题】:Detecting the environment in PHP CLI scripts在 PHP CLI 脚本中检测环境
【发布时间】:2011-12-12 16:53:53
【问题描述】:

我在 StackOverflow 上看到了几个问题,这些问题处理如何在通过 Apache 提供脚本时检测用户环境,并拥有这样一个完美运行的系统。 该脚本依赖于 Apache 设置的 Environment vars。

现在我正在创建几个需要在 php CLI 模式下运行的工具,但我不知道如何在 CLI 模式下检测环境,因为那里不存在 apache env var。

我正在考虑使用 gethostname() 读取服务器的主机名,但不知道这是否是最好的解决方案和可靠的解决方案。

使用 PHP 在 CLI 模式下运行时检测环境的最佳方法是什么

澄清:
我不是在寻找一种方法来检测我是否正在从 CLI 运行脚本,该基础已涵盖。我正在寻找一种方法来通过 CLI 方式确定我的脚本在哪个服务器上运行(DEV、STAGING 或 PRODUCTION),因此在通过浏览器运行相同脚本时不读取我的 VHOST 中设置的 apache env 变量。

【问题讨论】:

标签: php


【解决方案1】:

我有许多依赖 sh/Bash 环境变量的 cli 脚本,而且通常不止几个。为了让我的生活更轻松,我只是将它们全部加载进去。

输出是一个数组,其键等于 shell 环境变量名称,值是变量设置的字符串。

例如$env_var['HOME'] => "/home/user"

要使用此代码,请确保您运行的任何 shell 都支持 printenv 命令。

$sh_env_arr = explode(PHP_EOL, shell_exec('printenv'));
    foreach($sh_env_arr as $var_lines) {
        $vals = explode('=', $var_lines);

        /* Some shell vars can have multiple equals signs as part of the value.
        We need to make those into a single string */
        if (isset($vals[2])){
            foreach (range(2, count($vals)-1) as $i) {
                $vals[1] = $vals[1].'='.$vals[$i];
            }
        }
        if (!isset($vals[1])) {$vals[1] = "";}
        $env_var[$vals[0]] = $vals[1];
    }

我什至使用容器玩过这个游戏,因为您可以在启动时从主机传递环境变量。这有助于将敏感信息(数据库凭据等)导入脚本。

【讨论】:

    【解决方案2】:

    即使这是一个古老的线程,您也可以在 php.ini 中设置和检索变量,您可以在一个地方设置值并通过服务器或 cli 使用它们:

    在 php.ini 中:

    [PHP]
    MY_ENVIRONMENT = development
    
    ;;;;;;;;;;;;;;;;;;;
    ; About php.ini   ;
    ;;;;;;;;;;;;;;;;;;;
    ; PHP's initialization file, generally called php.ini, is responsible for...
    

    然后从 cli:

    php > echo get_cfg_var('MY_ENVIRONMENT');
    development
    

    和一个网页(注意:您必须重新启动 apache 才能使用此变量):

    <?php
    
    echo "you are in: " . get_cfg_var('MY_ENVIRONMENT');
    // you are in: development
    

    【讨论】:

      【解决方案3】:

      为了不定义两次环境变量,我做了以下(在 Ubuntu 中)。

      在 /etc/profile.d/env.sh 中定义你的变量,例如 导出 APPLICATION_ENV=生产

      通过添加以下行将该文件包含在 /etc/apache2/envvars 中: . /etc/profile.d/env.sh

      重启 apache2 和你的 shell 以重新加载环境。

      【讨论】:

        【解决方案4】:

        我会在/etc/environment(或基于操作系统风格的等效项)中设置变量,例如 MYAPP_ENV=STAGING.

        这将自动被 CLI php 运行时拾取并在 $_SERVER 全局变量中可用,如下所示: _$SERVER['MYAPP_ENV']

        如果您希望无论脚本是从 HTTPD 还是 CLI 运行,这都能正常工作,您还需要在 .htaccess 或 vhosts.conf apache 文件中为您的应用设置此变量(假设为 apache),如下所示: SetEnv MYAPP_ENV STAGING

        从您的应用程序代码中,您只需引用 _$SERVER 即可访问此变量,无论调用是来自 CLI 还是通过 http。

        很糟糕,您必须在您的机器上设置两次此变量 - 一次用于 Apache,一次用于 CLI,但至少从应用程序层您可以在读取环境变量时不知道执行运行时。

        【讨论】:

        • 这个答案应该被标记为解决方案。依赖主机名不是正确的做法,而且不可扩展。
        • 请注意,这仅在您以 root 身份运行 php cli 脚本时才有效。
        • 在 mac 上,您可以将此行添加到您的 .bash_profile 中:export APP_ENV_MYAPP=dev
        【解决方案5】:

        您可能需要设置 env 系统范围,而不仅仅是从 apache,然后 apache 脚本可以读取它并且 cli 脚本可以从 ENV 读取它,您可以通过 /etc/profile 将它们设置为交互式 shell,例如

        APP_ENV = '暂存'

        导出 APP_ENV

        (您可以通过这样的两行来执行此操作,以便稍后脚本中的其他内容也可以引用 APP_ENV 并获得相同的值,否则 APP_ENV 在重新运行之前对该 shell 无效)

        然后只需在 cli 或 apache 上从您的程序中检查 $_ENV ,但 apache 可能需要重新启动,因为我已经将其付诸实践已经有一段时间了,但它也非常适合用于 DB 连接的 json 编码设置,但仅此而已另一篇文章。

        【讨论】:

          【解决方案6】:

          我一直使用与服务器主机名匹配的命名: 想象主机名看起来像这样: - server.production.project.com - server.development.project.com

          您可以使用主机名和一些 bash(或 php)魔术来确定主机:

          $server_env = `hostname | cut -d \. -f 2`; # production or development
          # pure php (5.3+) method:
          $server_name = gethostname();
          $server_name_arr = explode( '.', $server_name );
          $server_env = $server_name_arr[1];
          

          主机名肯定应该不同;) 干杯

          【讨论】:

            【解决方案7】:

            您可以使用php_uname('n') 获取当前机器的主机名。从那里,由您的实现来确定它是生产、暂存还是开发,或者基于主机名中的模式、硬编码值或其他一些配置文件。

            【讨论】:

            • 似乎是目前最稳定的方法。应该特别注意不要在此之后更改主机名。
            • 多虚拟主机场景怎么样。我希望我可以根据当前目录和虚拟主机配置获取 ENV。
            【解决方案8】:
            $cli = false;
            if (isset($argc)) $cli = true;
            

            见:$argc

            【讨论】:

            • 我不是在寻找 CLI 检测,我需要环境检测,检测脚本在哪个服务器上运行,我在我的问题中进一步阐述了一点
            • 检测脚本在哪个服务器上的最可靠方法可能是在每台服务器上放置一个特殊文件,并使该文件成为部署过程的一部分。将 server.dev 文件放在开发服务器上,将 server.prod 放在生产服务器上,等等。许多应用程序更进一步,将配置本身放在服务器特定文件中(例如 config.dev、config.prod、config.stage )。然后,您的配置加载器仅测试每个文件是否存在,如果它们包含配置数据,则可以选择加载它们,并且您知道您在哪个服务器上并具有特定于服务器的配置。
            【解决方案9】:

            据我所知,您可以在 shell 中运行时使用 $_ENV 和 getenv(),就像在 Web 服务器下运行时一样,尽管 env 中可用的实际值可能会有所不同。

            【讨论】:

            • 是的,但是 PHP CLI 不知道在 apache 配置中设置的 SetEnv 变量。这就是我要解决的问题。
            【解决方案10】:

            我认为您的环境是指操作系统 - 并且有一种简单的方法可以从任何 PHP 实例(无论是否有 Apache)执行此操作:常量 PHP_OS 和函数 php_uname()

            如果您的意思是“检测它是否是 CLI”,只需测试 isset($GLOBALS['argv']) - 它不会使用网络服务器进行设置,如果它是 CLI 则会设置。或者你可以(PHP_SAPI === 'cli')

            【讨论】:

            • 我正在寻找两者都没有,因为我的登台和生产服务器都运行相同的操作系统,我不需要检测它是否是我正在运行的 CLI。检查OP,我已经详细说明了。
            • @ChrisR ...您如何在 Apache 下做到这一点? $_ENV 或以其他方式?即 Apache 环境变量从哪里获取值?
            • SetEnv in my vhost config en getenv() in PHP, 简单如馅饼:)
            猜你喜欢
            • 2016-03-31
            • 1970-01-01
            • 1970-01-01
            • 2019-12-12
            • 1970-01-01
            • 2020-07-02
            • 2013-08-25
            • 1970-01-01
            • 2011-11-04
            相关资源
            最近更新 更多