在 PHP CLI 脚本中检测环境

18
我在StackOverflow上看到了几个问题,这些问题涉及到如何检测在通过Apache服务的脚本中检测用户环境,并已经有了一个完美运行的系统。这个脚本依赖于由Apache设置的环境变量。
现在我正在创建多个需要在php CLI模式下运行的工具,但我不知道如何检测CLI模式下的环境,因为Apache环境变量在那里不存在。
我考虑使用gethostname()函数读取服务器的主机名,但不知道这是否是最佳且可靠的解决方案。
什么被认为是在PHP CLI模式下检测您的环境的最佳方法?
澄清: 我不是在寻找检测是否从CLI运行脚本的方法,这是可以解决的。我正在寻找一种通过CLI手段确定我的脚本正在哪台服务器(DEV、STAGING或PRODUCTION)上运行的方法,因此不能读取在通过浏览器运行相同脚本时设置的VHOST中存在的Apache env变量。

3
请注意,这不是那个问题的重复。那个问题关注如何判断脚本是从Web服务器还是命令行运行。这个问题更多地涉及到在命令行中运行时获取环境变量。 - GordonM
实际上,我在我的问题中进一步阐述了一些内容。 - ChrisR
你可以使用这个库:https://github.com/arcanisgk/WEB-CLI-Detector - user17161735
10个回答

13

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


1
目前来看,这似乎是最稳定的方法。但是在此之后,请格外小心不要更改主机名。 - Halil Özgür
2
多虚拟主机场景怎么样?我希望能够根据当前目录和虚拟主机配置获取ENV。 - Nikola
你可以使用这个库:https://github.com/arcanisgk/WEB-CLI-Detector - user17161735

12

我会将变量设置在/etc/environment(或根据操作系统版本相应的等效文件)中,例如MYAPP_ENV=STAGING

这将自动被CLI php runtime捡起,并作为全局变量出现在$_SERVER中,如下所示:_$SERVER['MYAPP_ENV']

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

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

很遗憾,您必须在计算机上两次设置此变量-一次为Apache,一次为CLI,但至少在应用程序层面上,当读取环境变量时,您可以对执行运行时保持不可知状态。


1
这个答案应该被标记为解决方案。依赖于主机名不是一个适当的方法,并且不可扩展。 - Laurent F
请注意,只有在以root身份运行php cli脚本时才能正常工作。 - Jiho Kang
在Mac上,你可以将以下这行代码添加到你的 .bash_profile 文件中:export APP_ENV_MYAPP=dev - ling

1

我一直使用命名匹配服务器主机名:

假设主机名看起来像这样:

  • 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];

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

1
为了避免重复定义环境变量,我在Ubuntu中采取了以下措施。
在/etc/profile.d/env.sh中定义您的变量,例如 export APPLICATION_ENV=production
通过添加以下行将该文件包含在/etc/apache2/envvars中: . /etc/profile.d/env.sh
重新启动apache2和您的shell以重新加载环境。

1

通过环境,我假设你指的是操作系统 - 无论是Apache还是其他任何PHP实例,都有一种绝对可靠的方法来执行此操作:使用常量PHP_OS和函数php_uname()

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


我不需要寻找两者中的任何一个,因为我的暂存和生产服务器都运行相同的操作系统,而且我不需要检测我正在运行的是否是CLI。请检查原帖,我有进一步阐述。 - ChrisR
@ChrisR...在Apache下如何实现呢?是用$_ENV还是其他方式?即Apache环境变量的值从哪里获取? - DaveRandom
在我的虚拟主机配置中设置SetEnv,然后在PHP中使用getenv(),简单易行 :) - ChrisR

1

你可能需要在整个系统设置环境变量,而不仅仅是在Apache中设置。这样,Apache脚本可以读取它,同时CLI脚本也可以从环境变量中读取到它。你可以通过在/etc/profile中为交互式shell设置它们,例如:

APP_ENV = 'staging'

export APP_ENV

(你需要用两行代码这样设置,这样脚本中的其他部分也可以引用APP_ENV并获取相同的值,否则APP_ENV在重新运行之前对该shell来说是不可用的)

然后,在CLI或Apache中的程序中检查$_ENV即可,但Apache可能需要重新启动。我已经有一段时间没有实践过这个了,但对于像JSON编码的数据库连接设置这样的情况非常好用,不过那是另外一个帖子的内容。


0
尽管这是一个古老的线程,但您仍然可以在php.ini中设置和检索变量,在那里您可以在一个地方设置值,并通过服务器或cli使它们可用:
在php.ini中:
[PHP]
MY_ENVIRONMENT = development

;;;;;;;;;;;;;;;;;;;
; About php.ini   ;
;;;;;;;;;;;;;;;;;;;
; PHP's initialization file, generally called php.ini, is responsible for...

然后从命令行界面:

php > echo get_cfg_var('MY_ENVIRONMENT');
development

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

<?php

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

0

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

输出是一个数组,键等于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];
    }

我甚至使用容器玩过这种游戏,因为您可以在启动时从主机传递环境变量。这对于将敏感信息(如数据库凭据等)传递到脚本中非常有帮助。


0
$cli = false;
if (isset($argc)) $cli = true;

请参见:$argc


我不是在寻找CLI检测,我需要环境检测,即检测脚本正在运行的服务器,我在我的问题中进一步阐述了这一点。 - ChrisR
可能最可靠的检测脚本所在服务器的方法是在每个服务器上放置一个特殊文件,并将该文件作为部署过程的一部分。在开发服务器上放置server.dev文件,在生产服务器上放置server.prod文件,以此类推。许多应用程序更进一步,将配置本身放在特定于服务器的文件中(例如config.dev、config.prod、config.stage)。然后,您的配置加载器只需测试每个文件是否存在,如果它们包含配置数据,则可以选择加载它们,这样您就知道自己在哪个服务器上并具有特定于服务器的配置。 - John Watson

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

5
是的,但是 PHP CLI 不知道在 Apache 配置中设置的 SetEnv 变量。这就是我正在尝试解决的问题。 - ChrisR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接