Intereting Posts
Аутентификация веб-браузера с сертификатом SSL PHP-Doctrine2: Items – Shops – ItemsAtShops – как удобно реализовать с помощью Doctrine2? Обнаружение конфликтов перекрытия событий календаря с использованием PHP Как найти первый / второй элемент ассоциативного массива, когда ключи неизвестны? PHP FPM возвращает HTTP 500 для всех ошибок PHP Загрузка URL-адреса PHP во Flash AS3 jQuery-токен-вход не обрабатывает междоменные результаты сортировка массива php внутри массива на основе значения UTF-8: русские символы и символ евро не отображаются и сохраняются в таблице mysql Ссылка php на файл изображения за пределами веб-каталога по умолчанию как предотвратить доступ к каталогу и показать запрещенную ошибку в php Круглое форматированное значение времени до ближайшего получаса autocomplete показывает все записи, не делает никакого поиска Как я могу использовать методы в PHP? Неопределенное смещение:

получать результат от команды shell_exec по мере запуска команды

Я кодирую веб-страницу с PHP-скриптом, предназначенную для приема имени файла изображения JFFS2, который ранее был загружен на сервер. Сценарий должен затем повторно воспроизвести раздел на сервере с изображением и вывести результаты. Я использовал это:

$tmp = shell_exec("update_flash -v " . $filename . " 4 2>&1"); echo '<h3>' . $tmp . '</h3>'; echo verifyResults($tmp); 

(Функция verifyResults вернет некоторый HTML-код, который указывает пользователю, успешно ли выполнена команда обновления. То есть, в случае успешного завершения обновления отобразите кнопку для перезапуска устройства и т. Д.).

Проблема заключается в том, что для выполнения команды обновления требуется несколько минут, а скрипт PHP блокируется до завершения команды оболочки до того, как она вернет какой-либо вывод. Обычно это означает, что команда обновления будет продолжена, в то время как пользователь увидит ошибку HTTP 504 (в худшем случае) или дождитесь загрузки страницы в течение нескольких минут.

Я думал о том, чтобы сделать что-то вроде этого:

 shell_exec("rm /tmp/output.txt"); shell_exec("update_flash -v " . $filename . " 4 2>&1 >> /tmp/output.txt &"); echo '<div id="output"></div>'; echo '<div id="results"></div>'; 

Это теоретически положило бы команду в фоновом режиме и добавит весь вывод в /tmp/output.txt.

И затем, в функции Javascript, я бы периодически запрашивал getOutput.php, который просто распечатывал содержимое /tmp/output.txt и вставлял его в div «output». Как только команда будет полностью выполнена, другая функция Javascript обработает вывод и отобразит результат в div «results».

Но проблема, которую я вижу здесь, заключается в том, что getOutput.php в конечном итоге станет недоступным во время обновления флеш-памяти устройства, потому что он находится на том сегменте, для которого предназначено обновление. Таким образом, это может оставить меня в том же положении, что и раньше, хотя и без страницы 504 или, казалось бы, бесконечно загружаемой страницы.

Я мог бы переместить getOutput.php на другой раздел в устройстве, но потом я думаю, что мне все равно придется делать какие-то напуганные вещи с конфигурацией веб-сервера, чтобы иметь возможность получить к нему доступ (символическая ссылка на него из webroot будет, как и любая другая файл, в конечном счете, будет перезаписан во время повторной вспышки).

Есть ли другой способ отображения вывода команды во время ее запуска, или я должен просто сделать это с решением, которое у меня есть?

Изменить 1: В настоящее время я тестирую некоторые решения. Я позже обновлю свой вопрос.

Изменить 2: Кажется, что файловая система не перезаписывается, как я думал изначально. Вместо этого система, похоже, монтирует существующую файловую систему в режиме только для чтения, поэтому я все еще могу получить доступ к getOutput.php даже после перезапуска файловой системы.

Второе решение, которое я описал в моем вопросе, похоже, работает в дополнение к использованию popen (как указано в ответе ниже) вместо shell_exec. Загрузка страницы, и через Ajax я могу отображать содержимое output.txt.

Однако кажется, что output.txt не отражает вывод команды re-flash в реальном времени – кажется, ничего не отображается, пока команда обновления не вернется из исполнения. Мне нужно будет продолжить тестирование, чтобы посмотреть, что здесь происходит.

Редактировать 3: Не обращайте внимания, похоже, что файл работает, когда я обращаюсь к нему. Я просто задерживал задержку, в то время как ядро ​​выполняло некоторые связанные с JFFS2 задачи, вызванные моим использованием раздела, на котором хранится исходное изображение JFFS2. Я не знаю почему, но это, по-видимому, заставляет все PHP-скрипты блокироваться, пока это не будет сделано.

Чтобы обойти это, я собираюсь включить вызов команды обновления в отдельный скрипт и запросить его через Ajax. Таким образом, пользователь, по крайней мере, получит некоторую предварительно упакованную обратную связь, пока технически все еще ждет в системе.

Посмотрите на popen: http://it.php.net/manual/en/function.popen.php

Интересный сценарий.

Моя первая мысль заключалась в том, чтобы что-то делать с proc_ * и $ _SESSION, но я не уверен, что это сработает или нет. Попробуйте, но если нет …

Если вы беспокоитесь о том, что файл во время процесса вспыхнул, вы всегда можете создать базу данных mysql во вторичном процессе и написать на это. База данных может существовать в другом разделе, и вы можете адресовать ее локальным ip, и система позаботится о маршрутизации.

редактировать

Когда я упоминал proc_ * с сеансами, я имел в виду нечто похожее на это, где $ descriptorspec стал бы:

 $_SESSION = array( 1 => array("pipe", "w"), ); 

Однако я сомневаюсь, что это сработает. Процесс завершится записью в $ _SESSION в памяти, которая больше не существует, когда первый скрипт убит.

Изменить 2

В этом случае вы можете установить memcache и записать вторичный процесс в память, который затем может быть перечитан вашим веб-интерфейсом.

Если вы уничтожите DocRoot, в это время нет ресурсов / скриптов, которые могут отвечать на запросы пользователя. Поэтому вы должны отправлять обновления пользователю в том же запросе, который выполняет очистку. Это требует, чтобы вы начали процесс оболочки и сразу возвращались к PHP. Это можно выполнить с помощью pcntl_fork() и pcntl_exec() . Ваш PHP-скрипт должен теперь непрерывно отправлять результат сценария оболочки клиенту. Если сценарий оболочки присоединяется к файлу в / tmp, вы можете fpassthru() этот файл и очистить его до окончания сценария оболочки.

Что касается вашего, тем не менее :

Я предполагаю, что вы пытаетесь использовать этот файл в качестве потока. Я не делал никаких производственных тестов, но считаю, что файл будет записан на диск только на fclose ().

Если вы постоянно пишете файл в скрипте # 2, эти записи фактически переходят непосредственно в память, пока файл не будет закрыт.

Опять же – я не могу это проверить, но если вы хотите протестировать его, попробуйте повторно открыть и закрыть файл для каждой записи. Это подтвердит или отклонит мою теорию, и вы можете соответствующим образом изменить свой подход.