интерактивное управление программой с использованием php

Я хотел бы запустить программу на удаленном компьютере с помощью php. Конечная цель – управлять программой с помощью веб-браузера на телефоне или на любом другом компьютере.

Моя программа C получает данные от разных датчиков в течение нескольких десятков минут. Он запускается из командной строки в Linux, и я могу отключить его, нажав клавишу «q» на клавиатуре компьютера. Основной поток – это примерно так:

int main(){ printf("Program is running... Press 'q' <enter> to quit\n"); fflush(stdout); //create one thread per sensor while (getchar() != 'q'){ } //ask the threads to terminate return(0); } 

Каждый поток выполняет некоторый printf, чтобы дать статус каждого датчика. Я хотел бы отслеживать это значение на своем телефоне и иметь кнопку для завершения удаленной программы.

Я могу успешно отслеживать значения, используя system (), open () или proc_open (). Это проблема getchar в основной программе. Он повесит скрипт php …

 <?php if(isset($_POST['start'])){ $descriptorspec = array( 0 => array("pipe", "r"), // // stdin est un pipe où le processus va lire 1 => array("pipe", "w"), // stdout est un pipe où le processus va écrire 2 => array("file", "/tmp/error-output.txt", "a") // stderr est un fichier ); $cwd = '/tmp'; $env = array(); $process = proc_open('/home/tristan/www/a.out', $descriptorspec, $pipes, $cwd, $env); if (is_resource($process)) { fwrite($pipes[0], 'q'); fclose($pipes[0]); echo stream_get_contents($pipes[1]); fclose($pipes[1]); $return_value = proc_close($process); echo "La commande a retourné $return_value\n"; } } ?> 

Использование fwrite($pipes[0], 'q'); работает хорошо, но скрипт php зависает, если я использую fwrite($pipes[0], ''); чтобы программа работала …

EDIT: я инвертировал проблему буферизации $process = proc_open('stdbuf -i0 /home/tristan/www/a.out', $descriptorspec, $pipes, $cwd, $env); безуспешно…

Кто-нибудь знает, как контролировать значения и отправлять команду в программу интерактивным способом?

Спасибо за помощь!

Solutions Collecting From Web of "интерактивное управление программой с использованием php"

Были проблемы с кодом PHP выше, которые позволяют вашей программе зависать:

  • stream_get_contents() будет висеть вечно, ожидая EOL который никогда не появляется, когда код C работает в бесконечном цикле. Вам нужно будет использовать stream_set_blocking() чтобы предотвратить stream_get_contents()

  • proc_close() также ожидает навсегда, если процесс не завершился. Что никогда не бывает из-за бесконечного цикла. Вам нужно будет его явно proc_terminate() с помощью proc_terminate() (что не имеет особого значения для imo)

Я подготовил пример того, как код не будет висеть, но я должен сказать, что ваш код не имеет большого смысла. Я бы закодировал программу C как демон UNIX, который слушает сокет домена UNIX. Затем вы можете создать простой текстовый протокол обмена для своих команд. Затем подключитесь к сокету в PHP. Но, возможно, я ошибаюсь, так как не знаю ваш сценарий приложения подробно.

Однако здесь идет ваш фиксированный код:

 $descriptorspec = array( 0 => array("pipe", "r"), // // stdin est un pipe où le processus va lire 1 => array("pipe", "w"), // stdout est un pipe où le processus va écrire 2 => array("file", "/tmp/error-output.txt", "a") // stderr est un fichier ); $cwd = '/tmp'; $env = array(); $process = proc_open(__DIR__ . '/a.out', $descriptorspec, $pipes, $cwd, $env); if (is_resource($process)) { fwrite($pipes[0], ' '); fclose($pipes[0]); // set stream to unblocking mode stream_set_blocking($pipes[1], 0); // now the following line will not wait forever // for an EOF echo stream_get_contents($pipes[1]); fclose($pipes[1]); // proc_close will wait until the process has finished - forever in this case // if you want to terminate the process. You'll have to terminate it explicitely proc_terminate($process); $return_value = proc_close($process); // if you want to have a meaningful return value // you'll have to implement a handler for SIGTERM // in your C program echo "La commande a retourné $return_value\n"; } 

Наконец, я получил то, что хотел использовать каналы в функции system ():

 <?php if(isset($_POST['start'])){ system('> /tmp/progOut'); system('mkfifo /tmp/progIn'); $proc = popen('./a.out < /tmp/progIn > /tmp/progOut &', 'r'); } ?>