Я пытаюсь сделать онлайн-судья для программирования 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 от никто
Три основных аспекта моего ответа
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"; } ?>