Каков канонический способ определения выполнения командной строки и http-скрипта PHP?

155

У меня есть сценарий PHP, который должен определить, был ли он выполнен через командную строку или через HTTP, главным образом для целей форматирования вывода. Какой канонический способ сделать это? Я думал, что это нужно для проверки SERVER['argc'], но оказывается, что это заполнено, даже при использовании серверного API Apache 2.0 Handler.

Бобби Джек
источник

Ответы:

228

Используйте php_sapi_name()функцию.

if (php_sapi_name() == "cli") {
    // In cli-mode
} else {
    // Not in cli-mode
}

Вот некоторые соответствующие заметки из документов:

php_sapi_name - возвращает тип интерфейса между веб-сервером и PHP

Хотя это и не является исчерпывающим, возможные возвращаемые значения включают aolserver, apache, apache2filter, apache2handler, caudium, cgi (до PHP 5.3), cgi-fcgi, cli, cli-server, непрерывность, embed, isapi, litespeed, milter, nsapi, phttpd, pi3web, roxen, thttpd, tux и webjames.

В PHP> = 4.2.0 также есть предопределенная константа PHP_SAPI, которая имеет то же значение, что и php_sapi_name().

Энди Флеминг
источник
Спасибо. Я заинтригован, почему док. Пример проверяет первые 3 символа, в то время как в описании говорится, что строка должна быть точно "cgi", но, кроме этого, я думаю, что это идеально.
Бобби Джек,
если, конечно, возвращенная строка не была 'cgi', что также указывает на то, что php выполняется из консоли. Как в моем случае.
Адриано Вароли Пьяцца
@Adriano: возможно, в вашем случае php-cgi используется для выполнения скрипта.
3
@Bobby, пример в документации php.net фактически совпадает с "cgi" и "cgi-fcgi", просто посмотрев на первые три символа строки ... вот почему, и это действительно имеет смысл. Во всяком случае, это просто чтобы вернуть @hop за вызов php без языка для серьезных программистов: D
ChrisR
1
Интересная заметка здесь: php.net/manual/en/function.php-sapi-name.php заключается в том, что в зависимости от фактического вызываемого двоичного файла , вы можете запустить php из командной строки и по-прежнему получать cgi-fgi
DAB
22

Это всегда будет работать. (Если версия PHP 4.2.0 или выше)

define('CLI', PHP_SAPI === 'cli');

Что облегчает использование в верхней части ваших скриптов:

<?php PHP_SAPI === 'cli' or die('not allowed');
Xeoncross
источник
8
Ваш второй фрагмент выглядит не как следствие, я бы ожидалCLI or die('not allowed');
Madbreaks
1
@ Madbreaks, я говорил о двух разных применениях. Я предполагал, либо один, либо другой - но если вы используете оба, то CLI or die('not allowed');это прекрасно.
Xeoncross
Спасибо за разъяснения, +1
Madbreaks
7
Which makes it easy to use at the top of your scriptsна самом деле не звучит как два отдельных использования. Да, я некромант.
Георгий Димитриадис
9

Вот реализация Drupal 7: drupal_is_cli () :

function drupal_is_cli() {
  return (!isset($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0)));
}

Однако Drupal 8 рекомендует использоватьPHP_SAPI === 'cli'

ya.teck
источник
8

думаю

$_SERVER['REMOTE_ADDR']

не будет заполнен из CLI.

Кроме того, все ключи HTTP_ * в суперглобальном файле $ _SERVER не будут заполняться из интерфейса командной строки, или делать это правильно, как только что упомянуто :-)

Винко Врсалович
источник
4

На странице документации для php_sapi_name четко указано, как это работает:

Возвращает строчную строку, которая описывает тип интерфейса (API сервера, SAPI), который использует PHP ....

Хотя это и не является исчерпывающим, возможные возвращаемые значения включают aolserver, apache, apache2filter, apache2handler, caudium, cgi (до PHP 5.3), cgi-fcgi, cli, непрерывность, embed, isapi, litespeed, milter, nsapi, phttpd, pi3web, roxen, thttpd, tux и webjames.

Я не уверен, почему Хоп не думает, что PHP предназначен для серьезных программистов (я серьезный программист, и я использую PHP ежедневно), но если он хочет помочь прояснить документацию, то, возможно, он может провести аудит всех возможных веб-серверов на котором может работать PHP и определять имена всех возможных типов интерфейсов для каждого сервера. Просто убедитесь, что этот список обновляется по мере добавления новых веб-серверов и интерфейсов.

Также Бобби сказал:

Я заинтригован, почему док. В примере проверяются первые 3 символа, а в описании указано, что строка должна быть точно "CGI".

Описание для примера гласит:

В этом примере проверяется подстрока cgi, поскольку она также может быть cgi-fcgi.

Стив
источник
Ах, или я был невероятно ненаблюдаемым в тот день, или пример был обновлен с тех пор, как я сделал этот комментарий. Тем не менее, искренне согласен с вашими соображениями по поводу PHP; избиение становится ОЧЕНЬ утомительным.
Бобби Джек