PHP: ¿cómo determinar mejor si la invocación actual es de CLI o servidor web?


Respuestas:


308

php_sapi_namees la función que querrá usar, ya que devuelve una cadena en minúsculas del tipo de interfaz. Además, existe la constante PHP PHP_SAPI.

La documentación se puede encontrar aquí: http://php.net/php_sapi_name

Por ejemplo, para determinar si PHP se está ejecutando desde la CLI, puede usar esta función:

function isCommandLineInterface()
{
    return (php_sapi_name() === 'cli');
}

11
Más sencillo:return php_sapi_name() == 'cli';
Savageman el

11
Hice una investigación: si invocas el script con php-cgiesto no funcionará. A su vez, devolverá cgi-fcgiString. Si carga el script como una página web desde un navegador, obtendrá apache2handler. Espero que esto ayude. Necesitaba usar php-cgicon el fin de introducir $_GETlas variables: php-cgi myscript.php arg1=one arg2=two. Las pruebas para no igual a apache2handlerdeberían estar bien para apache.
Sebastian

3
Una pequeña advertencia sobre este método: no volverá "cli"cuando se ejecute desde un trabajo cron. Hay un número de teclas diferentes para elegir dentro $_SERVERpara determinar de manera más confiable si la solicitud llegó a través de HTTP o no.
omninonsense

2
@omninonsense Probé con PHP 7.2.7 y devuelve cli.
Jose Nobile

38

He estado usando esta función por algunos años

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;
}

10
array_key_exists('REQUEST_METHOD', $_SERVER) return true;WAT?
biziclop

@biziclop, la verificación array_key_exists('REQUEST_METHOD', $_SERVER)es correcta para ayudar a detectar la fuente de la solicitud . Cuando está en CLI , la $_SERVERmatriz Super Global NO TENDRÁ la clave REQUEST_METHOD, solo existe cuando la solicitud se realiza a través de la Web, por lo tanto, el autor está absolutamente en el blanco al verificarlo.
Julio Marchi

1
@JulioMarchi: ¿pero no debería return false;hacerlo if ( ! array_key_exists(…)) return true;?
biziclop

2
@biziclop, tienes toda la razón !!!! ¿Cómo podría perderme ese pequeño y enorme detalle? Me avergüenza... :). Seguramente, si la clave 'REQUEST_METHOD'es NO encontró, entonces la función debe devolver FALSEpara indicar "línea de comandos". Mis disculpas por no prestar atención al alcance de la función en sí ... ¡El autor debería solucionarlo porque la función realmente funciona!
Julio Marchi

Esta función funcionó en mi caso, no php_sapi_name (), ya que necesitaba distinguir entre solicitudes web y ejecuciones de cronjob, y el resultado de php_sapi_name () fue "php-cgi" en ambos casos.
luis.ap.uyen

36

php_sapi_name()Realmente no es la mejor manera de realizar esta comprobación porque depende de la comprobación de muchos valores posibles. El binario php-cgi se puede llamar desde la línea de comandos, desde un script de shell o como un trabajo cron y (en la mayoría de los casos) estos también deberían tratarse como 'cli' pero php_sapi_name()devolverán valores diferentes para estos (tenga en cuenta que esto no es ' Es el caso con la versión simple de PHP, pero desea que su código funcione en cualquier lugar, ¿verdad?). Sin mencionar que el próximo año puede haber nuevas formas de usar PHP que posiblemente no podamos conocer ahora. Prefiero no pensar en ello cuando todo lo que me importa es el clima, debería envolver mi salida en HTML o no.

Afortunadamente, PHP tiene una forma de verificar esto específicamente. Simplemente use http_response_code()sin ningún parámetro y devolverá VERDADERO si se ejecuta desde un entorno de tipo de servidor web y FALSO si se ejecuta desde un entorno de tipo CLI. Aquí está el código:

$is_web=http_response_code()!==FALSE;

Esto incluso funcionará si accidentalmente (?) Establece un código de respuesta de un script que se ejecuta desde la CLI (o algo así como la CLI) antes de llamar a esto.


44
Esta pregunta ya era vieja cuando la respondí. Votar esta respuesta probablemente hubiera sido más útil que publicar otra respuesta que sea un duplicado, excepto sin la explicación.
krowe2

Con respecto a "Esto incluso funcionará si accidentalmente (?) Establece un código de respuesta de un script que se ejecuta desde la CLI ([...]) antes de llamar a esto": (al menos) a partir de PHP 7.4.3, esto es no es verdad. http_response_code()establece el código / devuelve el código establecido cuando se ejecuta desde la CLI. Verified by <?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(false); t();. Entonces, si http_response_code()===falsees una apuesta segura asumir CLI, pero si no, también debe verificar otras métricas.
Sebastian B.

23

Creo que quiere decir si se invoca PHP CLI o si es una respuesta de una solicitud web. La mejor manera sería usar el php_sapi_name()que, si estaba ejecutando una solicitud web, haría eco de Apache si eso es lo que estaba ejecutando.

Para enumerar algunos tomados de los documentosphp_sapi_name() php en :

  • servidor
  • apache
  • apache2filter
  • apache2handler
  • caudium
  • cgi (hasta PHP 5.3)
  • cgi-fcgi
  • cli
  • cli-server (servidor web incorporado a partir de PHP 5.4)
  • continuidad
  • empotrar
  • fpm-fcgi
  • isapi
  • velocidad media
  • milter
  • nsapi
  • phttpd
  • pi3web
  • roxen
  • thttpd
  • esmoquin
  • webjames

13

Esto debería manejar todos los casos (incluido php-cgi)

return (php_sapi_name() === 'cli' OR defined('STDIN'));

6
function is_cli() {
    return !http_response_code();
}

ejemplo:

if (is_cli()) {
    echo 'command line';
} else {
    echo 'browser';
}

2
Del manual, "FALSE se devolverá si no se proporciona respuesta_código y no se invoca en un entorno de servidor web (como desde una aplicación CLI). VERDADERO se devuelve si se proporciona respuesta_código y no se invoca en un servidor web entorno (pero solo cuando no se ha establecido un estado de respuesta anterior) ". Has conseguido tu lógica al revés.
krowe2

1
+1. Asombroso. Después de tantos años de investigación infructuosa ... por la presente le otorgo el Premio Nobel Memorial en PHPics, compartido con @ krowe2 por su invaluable contribución para que realmente funcione. ¡Felicidades!
Sz.

Es posible que algo haya configurado el código de respuesta ... http_response_code(200);... si ahora lo llamo http_response_code()devolverá 200;
Brad Kent

@BradKent Eso SÓLO si llama a esto desde un entorno web y, en ese caso, esta comprobación seguirá funcionando siempre que no haya configurado el código de estado a cero (que de todos modos es un código de estado HTTP no válido). Mi versión funcionará incluso en ese caso porque verifica específicamente FALSO. Si http_response_code();se llama desde un entorno CLI, siempre devolverá FALSE independientemente del código de estado real. Ya he explicado esto en mi respuesta, pero también podría haberlo descubierto leyendo la página del manual en "Valores de retorno" o probándolo.
krowe2

@ krowe2 php -r 'http_response_code(200); echo http_response_code()."\n";' genera "200" A menos que pueda garantizar que alguna biblioteca o marco ignorante no haya configurado el código de respuesta http_response_code(incluso en un entorno cli), esto funcionará. Personalmente, uso$isCli = \defined('STDIN') || isset($_SERVER['argv']) || \array_key_exists('REQUEST_METHOD', $_SERVER)
Brad Kent

4

Usé esto:

php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0)

Esto es de la base de código Drush, environment.inc donde tienen una verificación similar para hacer.


44
Si register_argc_argvestá configurado, pasar cualquier cantidad de valores GET hará argcque no sea 0.

3

Tratar

isset($_SERVER['REQUEST_METHOD'])

si está configurado, estás en un navegador.

Alternativamente, puede verificar si

isset($_SERVER['argv'])

pero eso podría no ser cierto en Windows CLI, IDK.


1
Aunque no es la respuesta "correcta", podría ser la más confiable
desafío


2

Joomla Way

if (array_key_exists('REQUEST_METHOD', $_SERVER)) die();

0

Sugeriría verificar si algunas de las entradas de la matriz $ _SERVER están configuradas.

P.ej:

if (isset($_SERVER['REQUEST_METHOD'])) {
        print "HTTP request\n";
} else {
        print "CLI invocation\n";
}

Esto no funcionará con la php-cgilínea de comando, lo configurará GETpara:php-cgi -f file.php arg1=2
Sebastian

0

Mi método preferido:

if (array_key_exists('SHELL', $_ENV)) {
  echo "Console invocation";
}
else {
  echo "HTTP invocation";
}

0
// Detect CLI calls
define("IS_CLI_CALL",( strcmp(php_sapi_name(),'cli') == 0 ));

if(IS_CLI_CALL){
   //do you stuff here

}

0

Una manera fácil es interrogar la $argvvariable, (lo que probablemente harás para los parámetros de la línea de comandos de todos modos). Incluso si no hay parámetros, $argvdevuelve una matriz vacía.

Si está configurado, entonces se usó cli. Luego puede suponer que todas las demás invocaciones se realizan a través de un servidor web u otro.

p.ej:

if (isset($argv)) {
  // Do the cli thing.
}

0

Basado en la respuesta anterior de Silver Moon , estoy usando esta función para devolver los saltos de línea correctos:

/**
* Linebreak function
* @return "/n" if cli, else return <br>
*/
protected static function lb(){

    return (defined('STDIN') || php_sapi_name() === 'cli' || isset($_ENV['SHELL']) ||
    (empty($_SERVER['REMOTE_ADDR']) && !isset($_SERVER['HTTP_USER_AGENT']) && count($_SERVER['argv']) > 0) ||
    !isset($_SERVER['REQUEST_METHOD'])) ? "\n" : "<br>";

}

0

La respuesta correcta a esta pregunta depende de la intención real detrás de ella:

  • ¿Es el SAPI el factor decisivo (contexto web o no)?
  • ¿O se interpreta la información como 'corriendo en un tty'?

Si lo primero, las respuestas dadas y los comentarios escritos son suficientes para encontrar una solución que funcione.

Si es esto último, las recetas dadas aquí fallarán si la herramienta se ejecuta como cronjob o como trabajo de fondo de otro demonio; en ese caso, sugiero probar más si STDINes un TTY:

function at_tty() {
    return defined("\STDIN") && posix_isatty(\STDIN);
}

-1

Cómo, tantas soluciones complicadas. Qué tal si ...

if($_SERVER['REQUEST_SCHEME']=="http" or $_SERVER['REQUEST_SCHEME']=="https"){
    // must be browser :)
}

-17

Lo intentaría:

echo exec('whoami');

Por lo general, los servidores web se ejecutan con un nombre de usuario diferente, por lo que debería ser revelador.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.