PHP: come determinare se l'invocazione corrente proviene dalla CLI o dal server Web?


Risposte:


308

php_sapi_nameè la funzione che vorrai utilizzare in quanto restituisce una stringa minuscola del tipo di interfaccia. Inoltre, c'è la costante PHP PHP_SAPI.

La documentazione è disponibile qui: http://php.net/php_sapi_name

Ad esempio, per determinare se PHP è in esecuzione dalla CLI, è possibile utilizzare questa funzione:

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

11
Più semplice:return php_sapi_name() == 'cli';
Savageman

11
Ho fatto una ricerca: se invochi la sceneggiatura con php-cgiquesto non funzionerà. A sua volta, restituirà cgi-fcgiString. Se carichi lo script come pagina web da un browser, otterrai apache2handler. Spero che questo ti aiuti. Avevo bisogno di utilizzare php-cgial fine di introdurre $_GETle variabili: php-cgi myscript.php arg1=one arg2=two. Test per non uguale a apache2handlerdovrebbe essere ok per apache.
Sebastian

3
Un piccolo avvertimento su questo metodo: sarà non ritorno "cli"quando viene eseguito da un job cron. Esistono diverse chiavi tra cui scegliere all'interno $_SERVERper determinare in modo più affidabile se la richiesta è arrivata via HTTP o meno.
omninonsense,

2
@omninonsense Ho provato con PHP 7.2.7 e restituisce cli.
Jose Nobile,

38

Uso questa funzione da alcuni anni

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, il controllo per array_key_exists('REQUEST_METHOD', $_SERVER)è corretto per aiutare il rilevamento della fonte della richiesta . Quando nella CLI , l' $_SERVERarray Super Global NON AVRÀ la chiave REQUEST_METHOD, esiste solo quando la richiesta viene effettuata via Web, quindi l'autore è assolutamente sulla destinazione quando lo controlla.
Julio Marchi,

1
@JulioMarchi: ma non è vero return false;o no if ( ! array_key_exists(…)) return true;?
biziclop,

2
@biziclop, hai perfettamente ragione !!!! Come potevo mancare tale enorme piccolo dettaglio ??? Mi vergogno... :). Sicuramente, se il KEY NON'REQUEST_METHOD' viene trovato, la funzione dovrebbe tornare a indicare "CLI". Mi scuso per non aver prestato attenzione all'ambito della funzione stessa ... L'autore dovrebbe risolverlo perché la funzione funziona davvero! FALSE
Julio Marchi,

Questa funzione ha funzionato nel mio caso, non in php_sapi_name (), poiché avevo bisogno di distinguere tra richieste web ed esecuzioni cronjob, e il risultato php_sapi_name () era "php-cgi" in entrambi i casi.
luis.ap.uyen,

36

php_sapi_name()non è davvero il modo migliore per eseguire questo controllo perché dipende dal controllo rispetto a molti valori possibili. Il binario php-cgi può essere chiamato dalla riga di comando, da uno script di shell o come cron job e (nella maggior parte dei casi) anche questi dovrebbero essere trattati come 'cli' ma php_sapi_name()restituiranno valori diversi per questi (nota che questo non è ' È il caso della versione normale di PHP ma vuoi che il tuo codice funzioni ovunque, giusto?). Per non parlare del fatto che il prossimo anno potrebbero esserci nuovi modi di usare PHP che non possiamo sapere ora. Preferirei non pensarci quando tutto ciò che mi interessa è il tempo dovrei avvolgere il mio output in HTML o no.

Fortunatamente, PHP ha un modo per verificarlo specificamente. Basta usare http_response_code()senza parametri e restituirà VERO se eseguito da un ambiente di tipo web server e FALSO se eseguito da un ambiente di tipo CLI. Ecco il codice:

$is_web=http_response_code()!==FALSE;

Funzionerà anche se imposti (?) Accidentalmente un codice di risposta da uno script in esecuzione dalla CLI (o qualcosa di simile alla CLI) prima di chiamarlo.


4
Questa domanda era già vecchia quando ho risposto. La votazione per eccesso di questa risposta sarebbe stata probabilmente più utile della pubblicazione di un'altra risposta che è duplicata se non senza la spiegazione.
krowe2,

Riguardo a "Funzionerà anche se imposti accidentalmente (?) Un codice di risposta da uno script in esecuzione dalla CLI ([...]) prima di chiamarlo.": (Almeno) a partire da PHP 7.4.3, questo è non vero. http_response_code()imposta il codice / restituisce il codice impostato durante l'esecuzione dalla CLI. Verificato da <?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();. Quindi se è http_response_code()===falseuna scommessa sicura assumere la CLI, ma in caso contrario è necessario controllare anche altre metriche.
Sebastian B.

23

Penso che significhi se la CLI di PHP viene invocata o se si tratta di una risposta da una richiesta web. Il modo migliore sarebbe quello di usare php_sapi_name()quale se fosse in esecuzione una richiesta web farebbe eco ad Apache se questo è quello che stava eseguendo.

Per elencare alcuni tratti dai documentiphp_sapi_name() php su :

  • AOLserver
  • apache
  • apache2filter
  • apache2handler
  • Caudium
  • cgi (fino a PHP 5.3)
  • cgi-fcgi
  • cli
  • cli-server ( Web server integrato a partire da PHP 5.4)
  • continuità
  • incorporare
  • FPM-fcgi
  • isapi
  • LiteSpeed
  • milter
  • NSAPI
  • phttpd
  • pi3web
  • Roxen
  • thttpd
  • Tux
  • webjames

13

Questo dovrebbe gestire tutti i casi (incluso php-cgi)

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

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

esempio:

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

2
Dal manuale, "FALSE verrà restituito se response_code non viene fornito e non viene richiamato in un ambiente server Web (ad esempio da un'applicazione CLI). TRUE verrà restituito se response_code viene fornito e non viene richiamato in un server Web ambiente (ma solo quando non è stato impostato uno stato di risposta precedente) ". Hai ottenuto la tua logica al contrario.
krowe2,

1
+1. Sorprendente. Dopo tanti anni di ricerche infruttuose ... Con la presente ti conferisco il Nobel Memorial Prize in PHPics, condiviso con @ krowe2 per il suo inestimabile contributo nel farlo effettivamente funzionare. Congratulazioni!
Sz.

È possibile che qualcosa abbia impostato il codice di risposta ... http_response_code(200);... se ora lo chiamo http_response_code()restituirà 200;
Brad Kent,

@BradKent Questo è SOLO se lo chiami da un ambiente web e, in tal caso, questo controllo continuerà a funzionare fintanto che non hai impostato il codice di stato su zero (che è comunque un codice di stato HTTP non valido). La mia versione funzionerà anche in quel caso perché verifica specificamente FALSE. Se http_response_code();viene chiamato da un ambiente CLI, restituirà sempre FALSE indipendentemente dal codice di stato effettivo. L'ho già spiegato nella mia risposta, ma potresti averlo scoperto anche leggendo la pagina del manuale in "Valori di restituzione" o provandolo.
krowe2,

@ krowe2 php -r 'http_response_code(200); echo http_response_code()."\n";' restituisce "200" A meno che non sia possibile garantire che alcune librerie o framework ignoranti non abbiano impostato il codice di risposta con http_response_code(anche in un client), allora funzionerà. Personalmente, io uso$isCli = \defined('STDIN') || isset($_SERVER['argv']) || \array_key_exists('REQUEST_METHOD', $_SERVER)
Brad Kent

4

Ho usato questo:

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

Questo proviene da Drush codebase, environment.inc dove hanno un controllo simile da fare.


4
Se register_argc_argvimpostato, il passaggio di qualsiasi quantità di valori GET argcnon sarà 0.

3

Provare

isset($_SERVER['REQUEST_METHOD'])

se è impostato, sei in un browser.

In alternativa, puoi verificare se

isset($_SERVER['argv'])

ma questo potrebbe non essere vero su Windows CLI, IDK.


1
Anche se non è la risposta "corretta", potrebbe essere la più affidabile
challet



0

Suggerirei di verificare se sono state impostate alcune delle voci dell'array $ _SERVER .

Per esempio:

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

Questo non funzionerà con la php-cgiriga di comando, lo imposterà GETsu:php-cgi -f file.php arg1=2
Sebastian

0

Il mio metodo preferito:

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

Un modo semplice è quello di interrogare la $argvvariabile (che probabilmente farai comunque per i parametri della riga di comando). Anche se non ci sono parametri $argvrestituisce un array vuoto.

Se è impostato, è stato utilizzato cli. Si può quindi presumere che tutte le altre invocazioni avvengano tramite un server Web o altro.

per esempio:

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

0

Sulla base della risposta di Silver Moon sopra , sto usando questa funzione per restituire le interruzioni di riga corrette:

/**
* 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 risposta corretta a questa domanda dipende dal vero intento che sta dietro:

  • La SAPI è il fattore decisivo (contesto Web o no)?
  • O le informazioni sono interpretate come "in esecuzione in un tty"?

Se il primo le risposte fornite e i commenti scritti sono sufficienti per trovare una soluzione che funzioni.

In quest'ultimo caso, le ricette fornite qui falliranno se lo strumento viene eseguito come cronjob o come processo in background da un altro demone - in tal caso suggerisco di testare ulteriormente se STDINè un TTY:

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

-1

Come, tante soluzioni complicate. Che ne dite di ...

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

-18

Proverei:

echo exec('whoami');

Di solito i server web sono gestiti con un nome utente diverso, quindi dovrebbe essere utile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.