Geçerli çağırma CLI veya web sunucusundan olup olmadığını en iyi nasıl belirlenir?


Yanıtlar:


308

php_sapi_namearabirim türünün küçük harfli dizesini döndürdüğü için kullanmak isteyeceğiniz işlevdir. Buna ek olarak, PHP sabiti vardır PHP_SAPI.

Belgeleri burada bulabilirsiniz: http://php.net/php_sapi_name

Örneğin, PHP'nin CLI'den çalıştırılıp çalıştırılmadığını belirlemek için bu işlevi kullanabilirsiniz:

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

11
Daha basit:return php_sapi_name() == 'cli';
Savageman

11
Bir araştırma yaptım: senaryoyu çağırırsanız php-cgibu işe yaramaz. Buna karşılık, cgi-fcgiString döndürür . Komut dosyasını bir tarayıcıdan web sayfası olarak yüklerseniz, alırsınız apache2handler. Bu yardımcı olur umarım. Ben kullanmak için gerekli php-cgitanıtmak amacıyla $_GETdeğişkenler: php-cgi myscript.php arg1=one arg2=two. Eşit olmayanlar için testler iyi apache2handlerolmalıdır apache.
Sebastian

3
Bu yöntemle ilgili küçük bir uyarı: Bu olacak değil dönmek "cli"bir cron işinden zaman koşmak. $_SERVERİsteğin HTTP üzerinden gelip gelmediğini daha güvenilir bir şekilde belirlemek için içinden seçim yapabileceğiniz birkaç farklı anahtar vardır .
omninonsense

2
@omninonsense PHP 7.2.7 ile test ettim ve cli döndürür.
Jose Nobile

38

Bu işlevi birkaç yıldır kullanıyorum

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, isteğin kaynağınınarray_key_exists('REQUEST_METHOD', $_SERVER) algılanmasına yardımcı olmak için denetim doğrudur . When in CLI , Süper Küresel dizisi OLACAK DEĞİL anahtarı VAR , sadece istek Web aracılığıyla yapıldığında bunun için kontrol ederken, dolayısıyla, yazar hedefte kesinlikle olduğunu bulunmaktadır. $_SERVERREQUEST_METHOD
Julio Marchi

1
@JulioMarchi: ama olmamalı return false;ya do if ( ! array_key_exists(…)) return true;?
biziclop

2
@biziclop, tamamen haklısın !!!! Böyle muazzam küçük detayları nasıl özleyebilirim ??? Bana yazıklar olsun ... :). KEY, muhakkak 'REQUEST_METHOD'edilir DEĞİL bulundu işlev dönmelidir FALSE"CLI" belirtmek için. Fonksiyonun kendisinin kapsamına dikkat etmemekten dolayı özür dilerim ... Yazar bunu düzeltmelidir çünkü fonksiyon gerçekten işe yarıyor!
Julio Marchi

Bu işlev, web istekleri ve cronjob yürütmeleri arasında ayrım yapmak gerektiğinden php_sapi_name () değil benim durumumda çalıştı ve her iki durumda da php_sapi_name () sonucu "php-cgi" idi.
luis.ap.uyen

36

php_sapi_name()bu kontrolü gerçekleştirmenin en iyi yolu değildir, çünkü birçok olası değere karşı kontrole bağlıdır. Php-cgi binary komut satırından, bir kabuk komut dosyasından veya bir cron işi olarak çağrılabilir ve (çoğu durumda) bunlar da 'cli' olarak ele alınmalı ancak php_sapi_name()bunlar için farklı değerler döndürülecektir (bunun t PHP'nin düz sürümüyle ilgili durum ancak kodunuzun herhangi bir yerde çalışmasını istiyorsunuz, değil mi?). Gelecek yıl, PHP'yi kullanmanın şimdi bilmediğimiz yeni yolları olabileceğinden bahsetmiyoruz bile. Önem verdiğim tek şey hava durumu olduğunda bunu düşünmemeyi tercih ederim.

Neyse ki, PHP'nin bunu özel olarak kontrol etmenin bir yolu var. http_response_code()Herhangi bir parametre olmadan kullanın ve bir web sunucusu türü ortamdan çalıştırıldıysa TRUE, CLI türü ortamlardan çalıştırıldıysa FALSE döndürür. İşte kod:

$is_web=http_response_code()!==FALSE;

Bunu, siz çağırmadan önce yanlışlıkla CLI'den (veya CLI gibi) bir komut dosyasından (?) Bir yanıt kodu ayarladıysanız bile çalışır.


4
Bu soru cevap verdiğimde zaten eskiydi. Bu cevaba oy vermek, açıklama yapmadan, mükerrer başka bir cevap göndermekten daha yararlı olabilirdi.
krowe2

"Bunu çağırmadan önce yanlışlıkla CLI'den ([...]) çalışan bir komut dosyasından bir yanıt kodu ayarladıysanız (?) İşe yarayacaktır.": (En azından) PHP 7.4.3'ten itibaren, bu doğru değil. http_response_code()kodu ayarlar / CLI'dan çalıştırırken set kodunu döndürür. Tarafından doğrulandı <?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();. Öyleyse http_response_code()===false, CLI'yi varsaymak güvenli bir bahisdir, ancak değilse diğer ölçümleri de kontrol etmeniz gerekir.
Sebastian B.

23

Bence PHP CLI çağrılıyorsa veya bir web isteğinden bir yanıt ise. En iyi yolu, php_sapi_name()bir web isteği çalıştırıyorsa, çalıştırdığı şey ise Apache'yi yankılayacağını kullanmaktır.

Üzerinde php dokümanlarphp_sapi_name() alınan birkaç listesini listelemek için :

  • aolserver
  • apache
  • apache2filter
  • apache2handler
  • caudium
  • cgi (PHP 5.3'e kadar)
  • cgi-fcgi
  • cli
  • cli-server ( PHP 5.4'ten itibaren yerleşik web sunucusu )
  • süreklilik
  • Göm
  • fpm-fcgi
  • ısapı
  • litespeed
  • erkek balık
  • nsapi
  • phttpd
  • pi3web
  • roxen
  • thttpd
  • smokini
  • webjames

13

Bu tüm durumları ele almalıdır (php-cgi dahil)

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

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

misal:

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

2
El kitabından, "response_code belirtilmezse ve bir web sunucusu ortamında (CLI uygulamasından olduğu gibi) çağrılmazsa FALSE döndürülür. Response_code sağlanırsa ve bir web sunucusunda çağrılmazsa TRUE döndürülür "(ancak daha önce yanıt durumu ayarlanmadığında). Mantığınızı geri aldınız.
krowe2

1
+1. İnanılmaz. Yıllarca süren verimsiz araştırmalardan sonra ... Bu vesileyle, PHP'nin Nobel Memorial Ödülü'nü size verdim. Tebrikler!
Sz.

Bir şey yanıt kodunu ayarlamış olabilir ... http_response_code(200);... şimdi http_response_code()ararsam 200 döndürür;
Brad Kent

@BradKent SADECE bunu bir web ortamından çağırırsanız ve bu durumda, durum kodunu sıfır olarak ayarlamadığınız sürece (yine de geçersiz bir HTTP durum kodu) bu kontrol çalışmaya devam eder. Benim sürümüm bu durumda bile çalışacaktır çünkü özellikle YANLIŞ'a karşı kontrol eder. Eğer http_response_code();bir CLI ortamdan denir her zaman fiili durum kodu ne olursa olsun FALSE dönecektir. Bunu cevabımda zaten açıkladım, ancak bunu "Dönüş Değerleri" altındaki manuel sayfayı okuyarak veya deneyerek de öğrenmiş olabilirsiniz.
krowe2

@ krowe2 php -r 'http_response_code(200); echo http_response_code()."\n";' çıktıları "200" Bazı kütüphane veya cahil çerçevenin yanıt kodunu http_response_code(bir cli env'de bile) ile ayarlamadığını garanti edemezseniz , bu işe yarayacaktır. Şahsen ben kullanıyorum$isCli = \defined('STDIN') || isset($_SERVER['argv']) || \array_key_exists('REQUEST_METHOD', $_SERVER)
Brad Kent

4

Bunu kullandım:

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

Bu Drush kod temeli, çevre yapmak için benzer bir kontrol var.


4
Eğer register_argc_argvayarlanır, daha sonra GET değerlerden herhangi miktarda geçen neden olacaktır argc0. olmamak için

3

Deneyin

isset($_SERVER['REQUEST_METHOD'])

ayarlanmışsa, tarayıcıdasınız demektir.

Alternatif olarak,

isset($_SERVER['argv'])

ancak bu windows CLI, IDK için geçerli olmayabilir.


1
"Doğru" cevap olmasa da, daha güvenilir olabilir
16:56


2

joomla yolu

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

0

$ _SERVER dizisinin bazı girişlerinin ayarlanıp ayarlanmadığını kontrol etmenizi öneririm .

Örneğin:

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

Bu php-cgikomut satırı ile çalışmaz , bunu şu şekilde ayarlayacaktır GET:php-cgi -f file.php arg1=2
Sebastian

0

Tercih ettiğim yöntem:

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

Kolay bir yol $argvdeğişkeni sorgulamaktır , (Muhtemelen komut satırı parametreleri için yapacaksınız). Hiçbir parametre olmasa bile $argvboş bir dizi döndürür.

Ayarlanmışsa, cli kullanıldı. Daha sonra, diğer tüm çağrıların bir web sunucusu veya başka bir sunucu aracılığıyla gerçekleştiğini varsayabilirsiniz.

Örneğin:

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

0

Yukarıdaki Silver Moon'un cevabına dayanarak , doğru çizgi çizgilerini döndürmek için bu işlevi kullanıyorum:

/**
* 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

Bu sorunun doğru cevabı, arkasındaki gerçek niyete bağlıdır:

  • SAPI karar verme faktörü mü (web bağlamında mı değil mi)?
  • Yoksa bilgi 'bir tty içinde koşuyor' olarak mı yorumlanıyor?

Eğer eski ise verilen cevaplar ve yapılan yorumlar işe yarayan bir çözüm bulmak için yeterlidir.

İkincisi, araç cronjob olarak veya başka bir arka plan programından arka plan işi olarak çalıştırılırsa burada verilen tarifler başarısız olacaktır - bu durumda STDINbir TTY olup olmadığını daha fazla test etmenizi öneririm :

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

-1

Nasıl, çok karmaşık çözümler. Peki ya ...

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

-18

Denerdim:

echo exec('whoami');

Genellikle web sunucuları farklı bir kullanıcı adı altında çalıştırılır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.