Как остановить PHP при применении команды терминала с помощью system () или passthru()?

#php

#php

Вопрос:

Я пытаюсь создать приложение, которое будет проверять, что оно может пинговать снаружи, но оно никогда не останавливается. Как я могу применить команду к терминалу и остановить действие? Пример в следующем случае:

 $ php -r "echo system('ping 127.0.0.1');"
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_req=1 ttl=64 time=0.073 ms
64 bytes from 127.0.0.1: icmp_req=2 ttl=64 time=0.073 ms
64 bytes from 127.0.0.1: icmp_req=3 ttl=64 time=0.072 ms
64 bytes from 127.0.0.1: icmp_req=4 ttl=64 time=0.074 ms
64 bytes from 127.0.0.1: icmp_req=5 ttl=64 time=0.071 ms
64 bytes from 127.0.0.1: icmp_req=6 ttl=64 time=0.073 ms
64 bytes from 127.0.0.1: icmp_req=7 ttl=64 time=0.074 ms
64 bytes from 127.0.0.1: icmp_req=8 ttl=64 time=0.073 ms
64 bytes from 127.0.0.1: icmp_req=9 ttl=64 time=0.074 ms
64 bytes from 127.0.0.1: icmp_req=10 ttl=64 time=0.081 ms
64 bytes from 127.0.0.1: icmp_req=11 ttl=64 time=0.072 ms
64 bytes from 127.0.0.1: icmp_req=12 ttl=64 time=0.075 ms
  

Примечание: для остановки были применены ctrl c, но это будет выполнено через веб-браузер.

Ответ №1:

Вы не можете. Вместо этого передайте -c аргумент в ping .

Комментарии:

1. Спасибо, $ ping -c 2 127.0.0.1 сработал. Но очень странно, если он продолжает работать бесконечное время. Разве мы не можем получить какую-либо команду, по которой мы запускаем ее ProcessId обратно в return или что-то в этомроде? И применить позже после sleep(4); kill(ProcessId); ?

2. Нет. Ни system() , ни passthru() не позволяйте PHP-скрипту запускаться, поэтому нет шансов остановить процесс.

3. Не совсем верно. Это невозможно сделать с помощью system() или passthru() , но это вполне возможно с помощью proc_open() .

Ответ №2:

Правильный курс действий — не останавливать процесс, а предоставить аргументы командной строки для ping, чтобы он завершился сам по себе. Аргумент, который вы ищете, заключается в -c count отправке только фиксированного количества запросов. Смотрите man ping для получения дополнительной информации.

Ответ №3:

system() является синхронным, поэтому вы не можете. Убедитесь, что дочерний процесс завершается.

В этом примере, ping -c 4 127.0.0.1 для отправки только четырех пакетов ping.

Ответ №4:

Это можно сделать с помощью proc_open . Например, эта программа позволит ping6 работать только около 5 секунд:

 <?php
$descriptorspec = array(
   1 => array("pipe", "w"),
);

$process = proc_open('ping6 ::1', $descriptorspec, $pipes);

$emptyarr = array();
$start = microtime(true);
if (is_resource($process)) {
    stream_set_blocking($pipes[1], 0);
    while (microtime(true) - $start < 5) {
        $pipesdup = $pipes;
        if (stream_select($pipesdup, $emptyarr, $emptyarr, 0, 100000))
            echo fread($pipes[1], 100);
    }

    fclose($pipes[1]);
    proc_terminate($process);
}
  

В вашем случае вы можете захотеть проверить connection_aborted() . Но обратите внимание, что вы должны продолжать отправлять (и сбрасывать) данные для обнаружения прерывания пользователя.

Комментарии:

1. Спасибо, я вижу, что в Zend Framework они сделали также: framework.zend.com/manual/en /…

2. Какой подробный, обратный подход, когда вы можете просто вызвать подпроцесс с правильными флагами.

3. @Tomalak 1) Это описывает общий подход, который будет работать для любого подпроцесса, а не только для ping; 2) Возможно, вы захотите запускать ping в течение неопределенного периода времени, пока пользователь не отменит.

4. Только начал использовать, это отлично работает, если вам нужно, вы тоже можете использовать это 🙂 stamped: gist.github.com/1008090