Как запустить команду linux для компиляции программы ac, из php-скрипта

Я пытаюсь сделать онлайн-судья для программирования c. Когда пользователь вводит код c и отправляет его, моя форма перенаправляется на файл jud.php, который является файлом действия для формы. Вот что я написал в jud.php

<?php $text=$_POST['code']; //echo $text; $var_str = var_export($text, true); file_put_contents('code.c', $text); $ans=exec('pwd'); $ans= exec('gcc code.c'); echo $ans; ?> 

Я захватил пользовательский ввод в текстовом формате и написал его в файл ac (code.c). До сих пор все нормально. Но exec(gcc code.c) не работает и не дает никакого вывода. Я пробовал другие коммуникационные линии, такие как pwd, date и т. Д. Они работают нормально. Что может быть причиной этого и как его исправить? Это не проблема с каталогом, которую я попробовал exec(pwd) и он дал результат как тот же каталог, в котором присутствует код. Я попытался запустить тот же файл code.c с терминала, и он работает нормально. Таким образом, это также не проблема «разрешения».

Еще одна вещь, как эхо генерировать сообщение об ошибке, если какая-либо команда exec () не работает должным образом?

Получив предложение из приведенного ниже ответа, я попробовал
$ cmd = "gcc -std = c99 code.c -g -Wall mysql_config --libs --cflags -o db_obj.o -pedantic";

 exec($cmd,$out,$status); 

Но он также не работает. Возвращаемый статус: 1

Скорее всего, это вопрос разрешения. «whoami» никому не говорит. Расскажите, как изменить владельца от кого-либо до корня или как назначить разрешение на выполнение gcc от никто

Related of "Как запустить команду linux для компиляции программы ac, из php-скрипта"

Три основных аспекта моего ответа

неправильное использование функции exec .

Посмотрите на страницы руководства . Во-первых, подпись функции exec :

 string exec ( string $command [, array &$output [, int &$return_var ]] ) 

Таким образом, exec может принимать до 3 аргументов. Он возвращает последнюю строку вывода команды, как и состояние документов:

Последняя строка из результата команды. Если вам нужно выполнить команду и получить все данные из команды, переданной непосредственно без каких-либо помех, используйте функцию passthru ().

Чтобы получить результат выполнения команды, обязательно установите и используйте выходной параметр.

Итак, в вашем случае:

 $lastLine = exec($command, $fullOutput, $status); 

Это то, что вы ищете. Если $status – это что то еще, кроме 0 , ваша команда не удалась. Вот что вы должны проверить, чтобы соответственно реагировать.
Полный вывод любой команды можно найти в $fullOutput в виде линейного массива.
Выход:

 all went well except for this 

Будет выглядеть так в массиве $fullOutput :

 array('all went well', 'except for this'); 

Разрешения могут быть проблемой, все еще.

Вы говорите, что разрешения не могут быть причиной проблемы, потому что вы можете запустить gcc из командной строки. Все отлично и денди, но какой пользователь использует PHP-скрипт на сервере?
В случае с веб-серверами этого пользователя часто называют никто , apache или что-то еще, и этому пользователю, скорее всего, не разрешено запускать gcc . Это PHP, который запускает новый экземпляр любой оболочки по умолчанию, которую он установил (возможно, bash), и это пользователь PHP, который входит в эту оболочку, и именно этот пользователь вызывает gcc

Знайте, кто вы, и к каким группам вы принадлежите. Попробуйте добавить это в свой скрипт:

 echo 'Script is running under user: ', exec('whoami'), '<br>', PHP_EOL; echo 'member of the following groups: ', exec('groups'), '<br>', PHP_EOL; 

И прежде чем вы спросите: да, это запятая … нет необходимости конкатенации, вы можете передать несколько переменных / значений для echo , разделенных запятой. Это на самом деле быстрее (подумайте об этом как о std::cout << some_var << another_var; C ++ std::cout << some_var << another_var; )

общие вопросы + безопасность

Это все сказано и сделано: компиляция кода C из php-скрипта не так проста, как вы, кажется, думаете, что это так. Предположим, я должен был написать это:

 #include <stdio.h> #include <time.h> int main ( void ) { time_t t = time(NULL); if (t%2) { float val = (float) t/2.0; //do stuff with float... } else { unsigned long long val = t/2; //do stuff with unsigned long long... } } 

Ваша команда gcc test.c завершится с ошибкой, потому что вам не удалось передать аргумент -std=c99 , например.
Если бы я хотел, чтобы скрипт скомпилировал данный файл, я также ожидал бы, что этот сценарий позволит мне выбрать, какие аргументы я скомпилировал с моим кодом, тоже -g , -Wall и, не говоря уже: cflags и libs (вывод pkg-config или mysql_config --cflags --libs , чтобы назвать конкретный пример, который я недавно использовал).
В принципе, ваш сценарий просто не может справиться с моим желанием скомпилировать что-то с помощью commind like

 gcc -std=c99 code.c -g -Wall `mysql_config --libs --cflags` -o db_obj.o --pedantic 

Которая все еще является упрощенной версией того, что многие команды компиляции выглядят, особенно при разработке отлаживаемого кода. Для стабильных выпусков вы, вероятно, можете сбросить -g и --pedantic , но вы получите мою точку зрения …
Подумайте, что это значит, позволяя пользователю передавать набор аргументов cli вместе с кодом. Они могут передавать аргумент типа -DSOME_MACRO или -O0 , что означает, что они также могут передать -O0 && rm -Rf * . Это означает, что вам нужно будет вызвать escapeshellcmd или escapeshellarg . Оба из них запретят мне передавать действительный аргумент:

 `mysql_config --libs --cflags` 

Что содержит обратные тики, и таким образом будет сбежать.

Чтобы быть откровенным, я изо всех сил стараюсь понять суть этого упражнения … и я оставляю много, все еще: опасности компиляции (не говоря уже о запуске) кода, предоставленного пользователем на вашем компьютере, например, не должны упускать из виду. Вы не можете просто скомпилировать код и запустить его на своем сервере: утечки памяти, segfaults … heck, чистый код зла все скомпилированы на вашем сервере без проверки, если это код, который у вас есть. На самом деле, спасите себе много слез и включите iframe, который загружает кодовое слово или какую-то подобную услугу …


Резюме:

  • всегда проверяйте человека на функцию, смотрите, получаете ли вы всю информацию, которую он возвращает
  • проверить разрешения и время выполнения для пользователя, который фактически выполняет команды
  • Никогда не доверяйте сети, не слепо предполагайте, что люди подадут действительный, безопасный код для компиляции.
  • Не заново изобретайте колесо: существуют службы компиляции, просто отправьте их (но сначала попросите разрешения)

Попробуйте этот код для выполнения c-программы из файла PHP

 <?php // used to compile the c file using exec() in php exec('gcc helloworld.c -o helloworld', $out, $status); if (0 === $status) { var_dump($out); // used to execute the c file using exec() in php exec('./helloworld', $out, $status); if (0 === $status) { var_dump($out); } else { echo "Command failed with status: $status"; } } else { echo "Command failed with status: $status"; } ?>