PHP zamanlı çıkışı ile çalıştırın süreç

7 Cevap php

Ben gerçek zamanlı çıktı döndürür bir web sayfası üzerinde bir işlemi çalıştırmak için çalışıyorum. Ben 'ping' süreci çalıştırmak Örneğin benim sayfa ben işlem görmeye bitinceye kadar-c seçeneği kullanmak ve beklemek zorunda kalıyorum ben exec (komut, çıkış) kullanmak zaman, şu anda (yeni bir satır döndürür her zaman güncellemek gerekir Benim web sayfasında çıktı). Bu php bunu yapmak mümkün mü?

Ben de birisi sayfa bırakarak zaman süreci bu tür öldürmek için doğru yolu nedir merak ediyorum. 'Ping' sürecinin durumda ben hala süreci (mantıklı) ne sistem monitör çalışan görmek mümkün.

7 Cevap

Bu benim için çalıştı:

$cmd = "ping 127.0.0.1";

$descriptorspec = array(
   0 => array("pipe", "r"),   // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),   // stdout is a pipe that the child will write to
   2 => array("pipe", "w")    // stderr is a pipe that the child will write to
);
flush();
$process = proc_open($cmd, $descriptorspec, $pipes, realpath('./'), array());
echo "<pre>";
if (is_resource($process)) {
    while ($s = fgets($pipes[1])) {
        print $s;
        flush();
    }
}
echo "</pre>";

Bu kabuk komutları gerçek zamanlı çıktı göstermek için güzel bir yoldur:

<?php
header("Content-type: text/plain");

// tell php to automatically flush after every output
// including lines of output produced by shell commands
disable_ob();

$command = 'rsync -avz /your/directory1 /your/directory2';
system($command);

Çıktı tamponlama önlemek için bu işlevi gerekir:

function disable_ob() {
    // Turn off output buffering
    ini_set('output_buffering', 'off');
    // Turn off PHP output compression
    ini_set('zlib.output_compression', false);
    // Implicitly flush the buffer(s)
    ini_set('implicit_flush', true);
    ob_implicit_flush(true);
    // Clear, and turn off output buffering
    while (ob_get_level() > 0) {
        // Get the curent level
        $level = ob_get_level();
        // End the buffering
        ob_end_clean();
        // If the current level has not changed, abort
        if (ob_get_level() == $level) break;
    }
    // Disable apache output buffering/compression
    if (function_exists('apache_setenv')) {
        apache_setenv('no-gzip', '1');
        apache_setenv('dont-vary', '1');
    }
}

Ben rağmen bunu denedim her sunucuda çalışmıyor, ben davranış bu tür işe almak için çalışırken saçını çekerek gerektiğini olup olmadığını belirlemek için php yapılandırması bakmak için tavsiyelerde ne isterdim sunucu üzerinde! Başka herkes biliyor musun?

İşte düz PHP bir kukla örnek:

<?php
header("Content-type: text/plain");

disable_ob();

for($i=0;$i<10;$i++) 
{
    echo $i . "\n";
    usleep(300000);
}

Ben bu burada kendi yolunu googled başkalarına yardımcı olur umarım.

Bu deneyin (Windows makine + wamp sunucu üzerinde test edilmiştir)

        header('Content-Encoding: none;');

        set_time_limit(0);

        $handle = popen("<<< Your Shell Command >>>", "r");

        if (ob_get_level() == 0) 
            ob_start();

        while(!feof($handle)) {

            $buffer = fgets($handle);
            $buffer = trim(htmlspecialchars($buffer));

            echo $buffer . "<br />";
            echo str_pad('', 4096);    

            ob_flush();
            flush();
            sleep(1);
        }

        pclose($handle);
        ob_end_flush();

Eğer PHP ile sistem komutları çalıştırmak için arıyorsanız, the exec documentation içine bakmak.

Ben oldukça ağır bir süreç olduğunu, ama bir yüksek trafik sitede bu iş her istek için bir süreç bölmek tavsiye etmem. Bazı programlar için kontrol ve irade süreci sonlandırmak olabilir böyle bir dosyaya kendi proses id yazma seçeneği sunar, fakat ping gibi komutlar için, ben adam sayfalarını kontrol, bu mümkün olduğundan emin değilim.

Uzak konak, her şeyi kullanıcı adasında iyi gidiyor, hem de ağ üzerinde olduğunu bildiğimiz yolda: Sen daha iyi sadece size (HTTP port 80 IE) dinleme bekliyoruz port üzerinde bir soket açarak servis edilebilir.

Eğer çıkış çalışıyorsanız ikili veri php's header function içine bakmak ve doğru content-type set sağlamak, ve content-disposition. Gözden the documentation, çıkış tamponu devre dışı bırakma / kullanma hakkında daha fazla bilgi için.

İlk flush() sizin için çalışıp çalışmadığını kontrol edin. Öyle Eğer değilse, iyi, muhtemelen örnek mod_gzip etkindir için web sunucusu, nedense tamponlama demektir.

Ping gibi bir şey için, en kolay teknik "ping-c 1" çalışan birden çok kez ve her çıkış sonra flush () çağırarak, PHP içinde döngü olduğunu. PHP HTTP bağlantı (genellikle varsayılan olan veya emin olmak için) (yanlış ignore_user_abort çağırabilirsiniz) kullanıcı tarafından kapatıldığında iptal etmek için yapılandırılmış olduğunu varsayarsak, o zaman da run-away ping süreçleri hakkında endişelenmenize gerek yok .

Bu sadece çocuk süreç once çalıştırın ve daha zor olabilir ki, sürekli çıkışını görüntülemek gerçekten gerekli ise - muhtemelen, arka planda çalıştırmak zorunda akışı çıktısını yönlendirmek, ve istiyorum Daha sonra PHP düzenli floş () çağrıları ile serpiştirilmiş, kullanıcıya geri olduğunu akışı yankı var.

Komut satırı kullanımı için:

function execute($cmd) {
    $proc = proc_open($cmd, [['pipe','r'],['pipe','w'],['pipe','w']], $pipes);
    while(($line = fgets($pipes[1])) !== false) {
        fwrite(STDOUT,$line);
    }
    while(($line = fgets($pipes[2])) !== false) {
        fwrite(STDERR,$line);
    }
    fclose($pipes[0]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    return proc_close($proc);
}

Eğer bir dosyayı çalıştırmak için çalışıyorsanız, bunu ilk çalıştırma izinlerini vermek gerekebilir:

chmod('/path/to/script',0755);