¿Cuál es la forma canónica de determinar la ejecución de la línea de comandos frente a http de un script PHP?

155

Tengo un script PHP que necesita determinar si se ejecutó a través de la línea de comandos o HTTP, principalmente con fines de formateo de salida. ¿Cuál es la forma canónica de hacer esto? Pensé que era para inspeccionar SERVER['argc'], pero resulta que esto está lleno, incluso cuando se usa la API del servidor 'Apache 2.0 Handler'.

Bobby Jack
fuente

Respuestas:

228

Usa la php_sapi_name()función.

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

Aquí hay algunas notas relevantes de los documentos:

php_sapi_name - Devuelve el tipo de interfaz entre el servidor web y PHP

Aunque no son exhaustivos, los posibles valores de retorno incluyen aolserver, apache, apache2filter, apache2handler, caudium, cgi (hasta PHP 5.3), cgi-fcgi, cli, cli-server, continuidad, embed, isapi, litespeed, milter, nsapi, phttpd, pi3web, roxen, thttpd, tux y webjames.

En PHP> = 4.2.0, también hay una constante predefinida PHP_SAPI, que tiene el mismo valor que php_sapi_name().

Andy Fleming
fuente
Gracias. Me intriga saber por qué el doc. ejemplo inspecciona los primeros 3 caracteres, mientras que la descripción indica que la cadena debe ser exactamente "cgi" pero, aparte de eso, creo que esto es perfecto.
Bobby Jack
a menos, por supuesto, que la cadena devuelta fuera 'cgi', lo que también indica que php se está ejecutando desde la consola. Como en, qué sabes, mi caso.
Adriano Varoli Piazza
@Adriano: tal vez en tu caso php-cgi se usa para ejecutar el script.
3
@Bobby, el ejemplo en los documentos de php.net en realidad coincide con "cgi" y "cgi-fcgi" simplemente mirando los primeros tres caracteres de la cadena ... es por eso y realmente tiene sentido. En todo caso, es solo volver a @hop por llamar a php sin lenguaje para programadores serios: D
ChrisR
1
Una nota interesante aquí: php.net/manual/en/function.php-sapi-name.php es que, dependiendo del binario real llamado, puede ejecutar php desde la línea de comandos y aún obtener cgi-fgi
DAB
22

Esto siempre funcionará. (Si la versión de PHP es 4.2.0 o superior)

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

Lo que facilita su uso en la parte superior de sus scripts:

<?php PHP_SAPI === 'cli' or die('not allowed');
Xeoncross
fuente
8
Su segundo fragmento parece un non sequitur, esperoCLI or die('not allowed');
Madbreaks
1
@Madbreaks, estaba indicando dos usos diferentes. Yo estaba asumiendo ya sea uno o el otro - pero si se utiliza tanto entonces CLI or die('not allowed');es perfecto.
Xeoncross
Gracias por aclarar, +1
Madbreaks
77
Which makes it easy to use at the top of your scriptsrealmente no suena como dos usos separados. Sí, soy nigromante.
George Dimitriadis
9

Aquí está la implementación de 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)));
}

Sin embargo, Drupal 8 recomienda usarPHP_SAPI === 'cli'

ya.teck
fuente
8

Yo creo que

$_SERVER['REMOTE_ADDR']

no se completará desde la CLI.

Además, todas las claves HTTP_ * en la superglobal $ _SERVER no se completarán desde la CLI, o lo harán de la manera correcta, solo mencioné :-)

Vinko Vrsalovic
fuente
4

La página de documentación de php_sapi_name indica claramente cómo funciona:

Devuelve una cadena en minúsculas que describe el tipo de interfaz (la API del servidor, SAPI) que PHP está utilizando ...

Aunque no son exhaustivos, los posibles valores de retorno incluyen aolserver, apache, apache2filter, apache2handler, caudium, cgi (hasta PHP 5.3), cgi-fcgi, cli, continuidad, incrustar, isapi, litespeed, milter, nsapi, phttpd, pi3web, roxen, thttpd, tux y webjames.

No estoy seguro de por qué hop no cree que PHP sea para programadores serios (soy un programador serio y uso PHP a diario), pero si quiere ayudar a aclarar la documentación, entonces quizás pueda auditar todos los servidores web posibles PHP puede ejecutarse y determinar los nombres de todos los tipos de interfaz posibles para cada servidor. Solo asegúrese de mantener esa lista actualizada a medida que se agreguen nuevos servidores web e interfaces.

Además, Bobby dijo:

Me intriga saber por qué el doc. ejemplo inspecciona los primeros 3 caracteres, mientras que la descripción indica que la cadena debe ser exactamente "CGI"

La descripción para el ejemplo dice:

Este ejemplo busca la subcadena cgi porque también puede ser cgi-fcgi.

Steve
fuente
Ah, o estaba siendo increíblemente inocente ese día, o el ejemplo se ha actualizado desde que hice ese comentario. Sin embargo, estoy totalmente de acuerdo con tus puntos sobre PHP; el ataque se vuelve muy cansado.
Bobby Jack