2016-09-29 1 views
0

У меня есть странная проблема. Я пытаюсь обойти буферизацию вывода в PHP, чтобы запускать вызовы system() и получать мгновенный вывод. Он работает очень хорошо, но по какой-то странной причине команда ping на «test.de» не отображает мгновенный вывод, поскольку пинг на google.de делает. Я вижу первую строку для «ping test.de» в оболочке linux мгновенно, но она не появляется сразу с этим скриптом. Кто-нибудь может помочь?Проблема с зависанием PHP с помощью буферизации вызовов и вывода passthru()/system()

<?php 

    // 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'); 
    } 

    header('Cache-Control: no-cache'); 

    $i=0; 
    while($i < 1000) { 
    $i++; 
    echo '      '; 
    } 
    echo '<pre>'; 
    echo "Pinging google.de \n\n"; 
    passthru("ping -w 10 -c 4 google.de"); 
    echo "\n\nPinging test.de \n\n"; 
    passthru("ping -w 10 -c 4 test.de"); 
    echo '</pre>'; 
?> 

Я пометил отсроченную линию в этом выводе:

Pinging google.de 

PING google.de (172.217.16.131) 56(84) bytes of data. 
64 bytes from zrh04s06-in-f131.1e100.net (172.217.16.131): icmp_seq=1 ttl=56 time=22.0 ms 
64 bytes from zrh04s06-in-f131.1e100.net (172.217.16.131): icmp_seq=2 ttl=56 time=22.0 ms 
64 bytes from zrh04s06-in-f131.1e100.net (172.217.16.131): icmp_seq=3 ttl=56 time=22.2 ms 
64 bytes from zrh04s06-in-f3.1e100.net (172.217.16.131): icmp_seq=4 ttl=56 time=22.0 ms 

--- google.de ping statistics --- 
4 packets transmitted, 4 received, 0% packet loss, time 3004ms 
rtt min/avg/max/mdev = 22.016/22.067/22.200/0.130 ms 


Pinging test.de 

PING test.de (104.45.6.189) 56(84) bytes of data. <<<< THAT line is delayed!! 

--- test.de ping statistics --- 
11 packets transmitted, 0 received, 100% packet loss, time 9999ms 

ответ

0

Я думаю, что это происходит потому, что вы используете функцию system(), как он будет возвращать только последнюю строку. Возможно, вам лучше всего подходят функции passthru() или exec(). Вот большая рецензия на то, что делают эти функции и их различия:

https://stackoverflow.com/a/21016100/1789650

Обновления на основе комментариев

Вы также можете попробовать добавление выходного аргумента вашего сценарий оболочки. Добавьте 2>&1 в конец вашей строки и поместите каждую новую выходную строку оболочки в переменную. Вот то, что он должен выглядеть следующим образом:

exec("ping -w 10 -c 4 google.de 2>&1", $output); 
print_r($output); 
+0

** 'Exec()' ** возвращает последнюю строку –

+0

Я уже пробовал 'EXEC()' и 'PassThru()'. Функция exec() недоступна для прямого вывода. passthru() звучало разумно, но это тоже не сработало. Он произвел такую ​​же задержку: -/Я также пробовал popen() и читал байты STDOUT байтом, но это тоже не сработало. Я также попытался отправить вывод в файл (с отдельной консолью) и сделать вызов system(), чтобы прочитать файл, а другой - записать его, но это тоже не сработало ... Я как бы застрял : -/ – xsign

+0

Добавьте переменную '$ output' и напечатайте аргумент экрана после команды, обновив ответ с помощью этой информации ... –

0

Решение:

Видимо, что-то делать с Linux буферизацией. Я переработал команду оболочки, так что теперь она работает. Решение состоит в том, чтобы обернуть команду linux командой script. Итак:

passthru("script -q -c 'ping -w 10 -c 4 test.de' /dev/null") 

Эта статья помогла: https://unix.stackexchange.com/questions/25372/turn-off-buffering-in-pipe

Смежные вопросы