PHP - 如何最好地确定当前调用是来自CLI还是Web服务器?

Sha*_*eem 184 php

我需要确定PHP的当前调用是来自命令行(CLI)还是来自Web服务器(在我的情况下,是带有mod_php的Apache).

任何推荐的方法?

Jor*_*nes 297

php_sapi_name是您要使用的函数,因为它返回接口类型的小写字符串.另外,还有PHP常量PHP_SAPI.

可在此处找到文档:http://php.net/php_sapi_name

例如,要确定是否从CLI运行PHP,可以使用此函数:

function isCommandLineInterface()
{
    return (php_sapi_name() === 'cli');
}
Run Code Online (Sandbox Code Playgroud)

  • 更直截了当:`return php_sapi_name()=='cli';` (11认同)
  • 我做了一个研究:如果用`php-cgi`调用脚本,这将无效.反过来,它将返回`cgi-fcgi`字符串.如果您从浏览器将脚本加载为网页,您将获得`apache2handler`.希望这可以帮助.我需要使用`php-cgi`来引入`$ _GET`变量:`php-cgi myscript.php arg1 = one arg2 = two`.测试不等于`apache2handler`对于`apache`应该没问题. (11认同)
  • 关于这个方法的一个小警告:当从cron作业运行时,它将*不*返回"cli".在$ _SERVER`中有一些od不同的键可供选择,以更可靠地确定请求是否来自HTTP. (3认同)
  • @omninonsense 我用 PHP 7.2.7 测试过,它返回 cli。 (2认同)

Sil*_*oon 36

我已经使用这个功能几年了

function is_cli()
{
    if ( defined('STDIN') )
    {
        return true;
    }

    if ( php_sapi_name() === 'cli' )
    {
        return true;
    }

    if ( array_key_exists('SHELL', $_ENV) ) {
        return true;
    }

    if ( empty($_SERVER['REMOTE_ADDR']) and !isset($_SERVER['HTTP_USER_AGENT']) and count($_SERVER['argv']) > 0) 
    {
        return true;
    } 

    if ( !array_key_exists('REQUEST_METHOD', $_SERVER) )
    {
        return true;
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

  • `array_key_exists('REQUEST_METHOD',$ _SERVER)返回true;`WAT? (9认同)
  • 我是否可以信任所有这些变量,或者 Web 用户是否有可能欺骗其中一个变量以获得应仅限于 CLI 上的用户的访问权限? (3认同)
  • @biziclop,你完全正确!!!! 我怎么能错过这样**巨大的**小细节?对我感到羞耻...... :).当然,如果找不到KEY`'REQUEST_METHOD'',那么函数应该返回`FALSE`来表示"CLI".我很抱歉不注意函数本身的范围......作者应该修复它,因为函数实际上有效! (2认同)

kro*_*we2 31

php_sapi_name()实际上不是执行此检查的最佳方法,因为它取决于检查许多可能的值.php-cgi二进制文件可以从命令行,shell脚本或作为cron作业调用,并且(在大多数情况下)这些也应该被视为'cli'但是php_sapi_name()会为这些返回不同的值(请注意,这不是'在普通版本的PHP的情况下,你希望你的代码在任何地方工作,对吗?).更不用说明年可能有新的方法来使用我们现在无法知道的PHP.当我关心的只是天气时,我宁愿不考虑它,我应该用HTML包装我的输出.

幸运的是,PHP有办法专门检查这一点.只使用http_response_code()没有任何参数,如果从Web服务器类型环境运行它将返回TRUE,如果从CLI类型环境运行则返回FALSE.这是代码:

$is_web=http_response_code()!==FALSE;
Run Code Online (Sandbox Code Playgroud)

如果你在调用它之前意外地(?)从运行CLI(或类似CLI)的脚本设置响应代码,这甚至可以工作.

  • 当我回答这个问题时,这个问题已经过时了.向上投票这个答案可能比发布另一个重复的答案更有用,除非没有解释. (3认同)
  • 你说得对,但为什么没有人投票给你答案呢? (2认同)
  • 关于“如果您在调用此函数之前不小心(?)从从 CLI ([...]) 运行的脚本中设置了响应代码,这甚至会起作用。”:(至少)从 PHP 7.4.3 开始,这是不对。从 CLI 运行时,`http_response_code()` 设置代码/返回设置的代码。通过 `<?php function t() { echo var_export(http_response_code(), true) 验证。' -> ' 。(http_response_code() !== false ? 'web' : 'cli') 。“\n”;} t(); http_response_code(200);t(); http_response_code(假);t();`。因此,如果“http_response_code()===false”,那么采用 CLI 是安全的选择,但如果不是,您还需要检查其他指标。 (2认同)

Mar*_*ler 23

我认为他的意思是,如果正在调用PHP CLI,或者它是来自Web请求的响应.最好的方法是使用php_sapi_name()它,如果它正在运行Web请求将回显Apache,如果它正在运行.

列出一些从php 文档中获取的php_sapi_name():

  • AOLserver的
  • 阿帕奇
  • apache2filter
  • apache2handler
  • Caudium服务器
  • cgi(直到PHP 5.3)
  • CGI-FCGI
  • CLI
  • cli-server(PHP 5.4 内置的Web服务器)
  • 连续性
  • FPM-FCGI
  • ISAPI
  • 的Litespeed
  • 雄鱼
  • NSAPI
  • phttpd
  • Pi3Web服务器
  • Roxen的
  • THTTPD
  • 晚礼服
  • webjames


rba*_*kar 13

这应该处理所有的情况(包括php-cgi)

return (php_sapi_name() === 'cli' OR defined('STDIN'));
Run Code Online (Sandbox Code Playgroud)


gnu*_*nud 7

尝试

isset($_SERVER['REQUEST_METHOD'])
Run Code Online (Sandbox Code Playgroud)

如果已设置,则您正在使用浏览器。

或者,您可以检查是否

isset($_SERVER['argv'])
Run Code Online (Sandbox Code Playgroud)

但在 Windows CLI、IDK 上可能并非如此。


Ter*_*Lin 5

function is_cli() {
    return !http_response_code();
}
Run Code Online (Sandbox Code Playgroud)

例:

if (is_cli()) {
    echo 'command line';
} else {
    echo 'browser';
}
Run Code Online (Sandbox Code Playgroud)

  • 从手册中,如果未提供response_code并且未在Web服务器环境中(例如从CLI应用程序)调用,则将返回FALSE.如果提供了response_code且未在Web服务器中调用,则将返回TRUE.环境(但仅在没有设置先前的响应状态时)".你已经倒退了你的逻辑. (2认同)