#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