(PHP 4, PHP 5, PHP 7, PHP 8)
exec — Выполнить внешнюю программу
Описание
exec(string $command, array &$output = null, int &$result_code = null): string|false
Список параметров
-
command -
Команда, которая будет исполнена.
-
output -
Если параметр
outputуказан, то
массив будет заполнен строками вывода программы.
Завершающие пробелы, такие какn,
не будут включены в массив. Обратите внимание, что если массив уже содержит
какие-либо элементы, то exec() добавит новые элементы в конец массива.
Если же вы не хотите, чтобы функция добавляла новые элементы в конец, вызовите
unset() на этом массиве, прежде чем передать его в exec(). -
result_code -
Если аргумент
result_codeприсутствует вместе с
output, тогда статус возврата выполненной команды
будет записан в этой переменной.
Возвращаемые значения
Последняя строка из результата команды. Если требуется
выполнить команду и получить все данные команды без какой-либо
обработки, используйте функцию passthru().
Возвращает false в случае возникновения ошибки.
Для получения результата выполнения команды, убедитесь, что параметр
output инициализирован и используется.
Ошибки
Выдаёт ошибку уровня E_WARNING, если функция exec()
не может выполнить команду command.
Выбрасывает исключение ValueError, если параметр command
не указан или содержит нулевые байты.
Список изменений
| Версия | Описание |
|---|---|
| 8.0.0 |
Если параметр command не указан или содержит нулевые байты,функция exec() теперь выбрасывает исключение ValueError; ранее она выдавала ошибку уровня E_WARNING и возвращала false.
|
Примеры
Пример #1 Пример функции exec()
<?php
// выводит имя пользователя, от имени которого запущен процесс php/httpd
// (применимо к системам с командой "whoami" в системном пути)
$output=null;
$retval=null;
exec('whoami', $output, $retval);
echo "Вернёт статус $retval и значение:n";
print_r($output);
?>
Результатом выполнения данного примера
будет что-то подобное:
Вернёт статус 0 и значение:
Array
(
[0] => cmb
)
Примечания
Внимание
Если вы собираетесь передавать функции пользовательские данные, используйте функции escapeshellarg() или escapeshellcmd() для того, чтобы пользователи не смогли обмануть систему, запустив произвольную команду.
Замечание:
Если вы собираетесь использовать эту функцию в программе, работающей в качестве демона, убедитесь, что стандартный вывод функции направлен в файл или другой поток, в противном случае PHP зависнет вплоть до конца выполнения программы.
Замечание:
В Windows функция exec() стартует cmd.exe для запуска команды. Если
вы хотите запустить внешнюю программу без запуска cmd.exe, то используйте
функцию proc_open() с установленной опцией
bypass_shell.
Смотрите также
- system() — Выполнить внешнюю программу и отобразить вывод
- passthru() — Выполнить внешнюю программу и отобразить необработанный вывод
- escapeshellcmd() — Экранировать метасимволы командной строки
- pcntl_exec() — Запустить указанную программу в области текущего процесса
- Оператор исполнения
Arno van den Brink ¶
14 years ago
This will execute $cmd in the background (no cmd window) without PHP waiting for it to finish, on both Windows and Unix.
<?php
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
?>
dell_petter at hotmail dot com ¶
13 years ago
(This is for linux users only).
We know now how we can fork a process in linux with the & operator.
And by using command: nohup MY_COMMAND > /dev/null 2>&1 & echo $! we can return the pid of the process.
This small class is made so you can keep in track of your created processes ( meaning start/stop/status ).
You may use it to start a process or join an exisiting PID process.
<?php
// You may use status(), start(), and stop(). notice that start() method gets called automatically one time.
$process = new Process('ls -al');// or if you got the pid, however here only the status() metod will work.
$process = new Process();
$process.setPid(my_pid);
?>
<?php
// Then you can start/stop/ check status of the job.
$process.stop();
$process.start();
if ($process.status()){
echo "The process is currently running";
}else{
echo "The process is not running.";
}
?>
<?php
/* An easy way to keep in track of external processes.
* Ever wanted to execute a process in php, but you still wanted to have somewhat controll of the process ? Well.. This is a way of doing it.
* @compability: Linux only. (Windows does not work).
* @author: Peec
*/
class Process{
private $pid;
private $command;
public function
__construct($cl=false){
if ($cl != false){
$this->command = $cl;
$this->runCom();
}
}
private function runCom(){
$command = 'nohup '.$this->command.' > /dev/null 2>&1 & echo $!';
exec($command ,$op);
$this->pid = (int)$op[0];
}
public function
setPid($pid){
$this->pid = $pid;
}
public function
getPid(){
return $this->pid;
}
public function
status(){
$command = 'ps -p '.$this->pid;
exec($command,$op);
if (!isset($op[1]))return false;
else return true;
}
public function
start(){
if ($this->command != '')$this->runCom();
else return true;
}
public function
stop(){
$command = 'kill '.$this->pid;
exec($command);
if ($this->status() == false)return true;
else return false;
}
}
?>
Simon ¶
8 years ago
Can’t get the output from your exec’d command to appear in the $output array?
Is it echo’ing all over your shell instead?
Append "2>&1" to the end of your command, for example:
exec("xmllint --noout ~/desktop/test.xml 2>&1", $retArr, $retVal);
Will fill the array $retArr with the expected output; one line per array key.
msheakoski @t yahoo d@t com ¶
18 years ago
I too wrestled with getting a program to run in the background in Windows while the script continues to execute. This method unlike the other solutions allows you to start any program minimized, maximized, or with no window at all. llbra@phpbrasil's solution does work but it sometimes produces an unwanted window on the desktop when you really want the task to run hidden.
start Notepad.exe minimized in the background:
<?php
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("notepad.exe", 7, false);
?>
start a shell command invisible in the background:
<?php
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("cmd /C dir /S %windir%", 0, false);
?>
start MSPaint maximized and wait for you to close it before continuing the script:
<?php
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("mspaint.exe", 3, true);
?>
For more info on the Run() method go to:
http://msdn.microsoft.com/library/en-us/script56/html/wsMthRun.asp
krjdev at gmail dot com ¶
1 year ago
Note for OpenBSD users:
In the default configuration from OpenBSD, PHP runs into a chroot. So the exec() command will not work. You will get a 127 (command not found) result code. The reason is, the shell (/bin/sh) is missing in chroot, but the exec() command requires the shell.
A quick and dirty solution is to copy /bin/sh (which is statically linked) in the chroot directory:
<?php
$ cp /bin/sh /var/www/bin
?>
(I have noticed this on OpenBSD 7.0 with PHP 8.0.11.)
ivk ¶
1 year ago
result_code -1 could mean "Maximum number of file descriptors reached". Check count(get_resources('stream')) and ulimit -Sn
Farhad Malekpour ¶
15 years ago
If you're trying to use exec in a script that uses signal SIGCHLD, (i.e. pcntl_signal(SIGCHLD,'sigHandler');) it will return -1 as the exit code of the command (although output is correct!). To resolve this remove the signal handler and add it again after exec. Code will be something like this:
...
pcntl_signal(SIGCHLD, 'sigHandler');
...
...
(more codes, functions, classes, etc)
...
...
// Now executing the command via exec
// Clear the signal
pcntl_signal(SIGCHLD, SIG_DFL);
// Execute the command
exec('mycommand',$output,$retval);
// Set the signal back to our handler
pcntl_signal(SIGCHLD, 'sigHandler');
// At this point we have correct value of $retval.
Same solution can apply to system and passthru as well.
Bob-PHP at HamsterRepublic dot com ¶
17 years ago
exec strips trailing whitespace off the output of a command. This makes it impossible to capture signifigant whitespace. For example, suppose that a program outputs columns of tab-delimited text, and the last column contains empty fields on some lines. The trailing tabs are important, but get thrown away.
If you need to preserve trialing whitespace, you must use popen() instead.
Paul Sommer ¶
6 years ago
I tried to execute a command in background under Windows.
After struggling for hours with all these half ready examples I would like to share the syntax I found working (for windows at least). This is not tested under Linux as there are more elegant ways to spawn a process.
Based on the function from Arno van den Brink.
<?php
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
?>
This works perfectly with e.g.
<?php
execInBackground('del c:tmp*.*')
?>
but the following does NOT work:
<?php
execInBackground('"c:path with spacesmy program.exe"')
?>
Why?
When windows sees quotation marks (") it thinks this is the window title, not the command.
So, when your command needs quotation marks you HAVE TO provide a window name first, like
execInBackground(""title"" ""c:path with spacesmy program.exe")
Quotation marks are mandatiory for window title. Otherwise windows thinks this is the program name.
Weired, but "Hey! it's Windows!" :)
hans at internit dot NO_SPAM dot com ¶
20 years ago
From what I've gathered asking around, there is no way to pass back a perl array into a php script using the exec function.
The suggestion is to just print out your perl array variables at the end of your script, and then grabbing each array member from the array returned by the exec function. If you will be passing multiple arrays, or if you need to keep track of array keys as well as values, then as you print each array or hash variable at the end of your perl script, you should concatenate the value with the key and array name, using an underscore, as in:
foreach (@array) print "(array name)_(member_key)_($_)" ;
Then you would simply iterate through the array returned by the exec function, and split each variable along the underscore.
Here I like to especially thank Marat for the knowledge. Hope this is useful to others in search for similar answer!
layton at layton dot tk ¶
18 years ago
This is the second time this one got me, I thought someone else might find this note useful too.
I am creating a long running exec'd process that I can access with page submissions up to 2 hours later. The problem is this, the first time I access the page everything works like it should. The second time the web browser waits and waits and never gets any messages -- the CPU time is not affected so it is apparent that something is blocked.
What is actually happening is that all of the open files are being copied to the exec'd process -- including the network connections. So the second time I try to access the web page, I am being given the old http network connection which is now being ignored.
The solution is to scan all file handles from 3 on up and close them all. Remember that handles 0, 1, and 2 are standard input, standard output, and standard error.
elwiz at 3e dot pl ¶
12 years ago
On Windows-Apache-PHP servers there is a problem with using the exec command more than once at the same time. If a script (with the exec command) is loaded more than once by the same user at the same time the server will freeze.
In my case the PHP script using the exec command was used as the source of an image tag. More than one image in one HTML made the server stop.
The problem is described here (http://bugs.php.net/bug.php?id=44942) toghether with a solution - stop the session before the exec command and start it again after it.
<?php
session_write_close
();
exec($cmd);
session_start();?>
juan at laluca dot com ¶
12 years ago
I was trying to get an acceslist from a remote computer by executing cacls and parse it in php, all in a Windows environment with Apache. First i discovered psexec.exe from Windows SysInternals.
But with the following line, I didn´t get anything, it get hunged, although from the command line it worked nice:
<?php exec ('c:\WINDOWS\system32\psexec.exe \192.168.1.224 -u myuser -p mypassword -accepteula cacls c:\documents\RRHH && exit', $arrACL ); ?>
To make it work I just followed the next steps:
- execute services.msc and find the apache service (In my case wampapache)
- Right button>Log On tab and change from Local System Account to a user created account, enter the username and the password and restart the service.
(I added this user to the administrators group to avoid permissions problems but its not recommended...)
It worked! And it may work with IIS too so try it if you have the same poblem....
Hope this helps someone, and sorry for my english
Martin Lakes ¶
12 years ago
Took quite some time to figure out the line I am going to post next. If you want to execute a command in the background without having the script waiting for the result, you can do the following:
<?php
passthru("/usr/bin/php /path/to/script.php ".$argv_parameter." >> /path/to/log_file.log 2>&1 &");
?>
There are a few thing that are important here.
First of all: put the full path to the php binary, because this command will run under the apache user, and you will probably not have command alias like php set in that user.
Seccond: Note 2 things at the end of the command string: the '2>&1' and the '&'. The '2>&1' is for redirecting errors to the standard IO. And the most important thing is the '&' at the end of the command string, which tells the terminal not to wait for a response.
Third: Make sure you have 777 permissions on the 'log_file.log' file
Enojy!
php dot reg at kjpetrie dot co dot uk ¶
5 months ago
If you want to run the command in the background and also use escapeshellcmd() as recommended, ensure you do the redirection outside the brackets! These are things you do want the shell to interpret.
E.g. exec(escapeshellcmd('mycommand and arguments').' > /dev/null &');
alvaro at demogracia dot com ¶
12 years ago
In Windows, exec() issues an internal call to "cmd /c your_command". This implies that your command must follow the rules imposed by cmd.exe which includes an extra set of quotes around the full command:
- http://ss64.com/nt/cmd.html
Current PHP versions take this into account and add the quotes automatically, but old versions didn't.
Apparently, the change was made in PHP/5.3.0 yet not backported to 5.2.x because it's a backwards incompatible change. To sum up:
- In PHP/5.2 and older you have to surround the full command plus arguments in double quotes
- In PHP/5.3 and greater you don't have to (if you do, your script will break)
If you are interested in the internals, this is the source code:
sprintf(cmd, "%s /c "%s"", TWG(comspec), command);
It can be found at http://svn.php.net/viewvc/ (please find php/php-src/trunk/TSRM/tsrm_win32.c, the comment system doesn't allow the direct link).
Hypolite Petovan ¶
2 years ago
On Unix, to execute a command $cmd in the background, the one and only allowed standard output redirection syntax is "> /path/to/file &". No other valid standard output redirection syntax will allow a command to be ran in the background.
<?php
// The following will be ran in the background
exec($cmd . " > /path/to/file &"); // All the following will NOT be ran in the background
exec($cmd . " >> /path/to/file &");
exec($cmd . " &> /path/to/file &");
exec($cmd . " &>> /path/to/file &");
exec($cmd . " 2>&1 > /path/to/file &");
exec($cmd . " 2>&1 >> /path/to/file &");
?>
bahri at bahri dot info ¶
13 years ago
[NOTE BY danbrown AT php DOT net: The following is a Linux script that the contributor of this note suggests be placed in a file named 'pstools.inc.php' to execute a process, check if a process exists, and kill a process by ID. Inspired by the Windows version at http://php.net/exec#59428 ]
<?php
function PsExecute($command, $timeout = 60, $sleep = 2) {
// First, execute the process, get the process ID
$pid = PsExec($command);
if(
$pid === false )
return false;
$cur = 0;
// Second, loop for $timeout seconds checking if process is running
while( $cur < $timeout ) {
sleep($sleep);
$cur += $sleep;
// If process is no longer running, return true;
echo "n ---- $cur ------ n";
if( !
PsExists($pid) )
return true; // Process must have exited, success!
}
// If process is still running after timeout, kill the process and return false
PsKill($pid);
return false;
}
function
PsExec($commandJob) {
$command = $commandJob.' > /dev/null 2>&1 & echo $!';
exec($command ,$op);
$pid = (int)$op[0];
if(
$pid!="") return $pid;
return
false;
}
function
PsExists($pid) {
exec("ps ax | grep $pid 2>&1", $output);
while( list(,
$row) = each($output) ) {
$row_array = explode(" ", $row);
$check_pid = $row_array[0];
if(
$pid == $check_pid) {
return true;
}
}
return
false;
}
function
PsKill($pid) {
exec("kill -9 $pid", $output);
}
?>
dr_jones153 at hotmail dot com ¶
15 years ago
If SAFE_MODE is on, and you are trying to run a script in the background by appending "> /dev/null 2> /dev/null & echo $!" to the command line, the browser will hang until the script is done.
My solution:
Create a shell script (ex. runscript.sh) which contains the execution line for the script you are trying to run in the background.
The runscript.sh is run by an exec() call without the redirect string, which is now placed in the runscript.sh.
runscript.sh will return almost immediately because output of the original script is redirected, and so will not hang your browser and the script runs fine in the background.
Команда exec не работает на моем сервере, она ничего не делает, у меня отключен safe_mode, и я убедился, что все консольные команды работают, я пробовал использовать абсолютные пути. Я проверил разрешения для приложений, и все приложения, которые мне нужны, имеют разрешения на выполнение. Я не знаю, что еще делать, вот краткое изложение кодов, которые я пробовал:
echo exec(‘/usr/bin/whoami’);
echo exec(‘whoami’);
exec(‘whoami 2>&1’,$output,$return_val);
if($return_val !== 0) {
echo ‘Error<br>’;
print_r($output);
}
exec(‘/usr/bin/whoami 2>&1’,$output,$return_val);
if($return_val !== 0) {
echo ‘Error<br>’;
print_r($output);
}
Вот вывод последних двух кодов:
Error
Array ( )
Я связался со службой сервера, и они не могут мне помочь, они не знают, почему команда exec не работает.
Ответ 1
Посмотрите файл /etc/php.ini:
; Эта директива позволяет отключить определенные функции в целях безопасности.
; Она получает список имен функций, разделенных запятыми. Эта директива
; *НЕ* зависит от того, включен или выключен безопасный режим.
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.disable-functions
disable_functions =
Убедитесь, что exec не определен следующим образом:
disable_functions=exec
Если это так, то просто удалите эту строку и перезапустите apache.
Для облегчения отладки я обычно запускаю файл php вручную (можно запросить вывод на большее число ошибок, не определяя их в основном ini). Для этого добавьте заголовок:
#!/usr/bin/php
ini_set(«display_errors», 1);
ini_set(«track_errors», 1);
ini_set(«html_errors», 1);
error_reporting(E_ALL);
в начало файла, дайте им права доступа chmod +x myscript.php и выполните ./myscript.php. Надо быть осторожным при выполнении данных операций, особенно на загруженном сервере, который много пишет в файл журнала.
И еще дополнительно: это похоже на проблемы с разрешениями. Создайте сценарий bash, который делает что-нибудь простое, echo «hello world»,и попробуйте его запустить. Убедитесь, что у вас есть разрешения для файла и для папки, содержащей файл.
Ответ 2
Поскольку вы выходите из контекста PHP в собственную оболочку, у вас будет много проблем с отладкой.
Лучшее и самое надежное, что я использовал, — это запись вывода скрипта в файл журнала и его отслеживание во время выполнения PHP.
<?php
shell_exec(«filename > ~/debug.log 2>&1»);
Затем в отдельной оболочке:
tail -200f ~/debug.log
Когда вы выполняете свой PHP-скрипт, ваши ошибки и выходные данные вашего вызова оболочки будут отображаться в вашем файле debug.log.
Ответ 3
Вот несколько вариантов решения вашей проблемы:
Для отладки всегда оборачивайте вашу функцию exec/shell_exec в var_dump().
error_reporting(-1); должен быть включен, как и display_errors, в крайнем случае даже set_error_handler(«var_dump»); — хотя бы для того, чтобы проверить, не вызвал ли сам PHP execvp или что-то еще.
Используйте 2>&1(объедините оболочки STDERR с потоком STDOUT), чтобы узнать, почему вызов не удался.
В некоторых случаях вам может потребоваться заключить вашу команду в дополнительный вызов оболочки:// захват потока STDERR через стандартную оболочку
echo shell_exec(«/bin/sh -c ‘ffmpeg -opts 2>&1’ «);
Чередуйте различные функции exec для выявления сообщений об ошибках. Хотя в основном они делают одно и то же, пути возврата выходных данных различаются:
- exec()— либо возвращает результат как результат функции, либо через необязательный параметр $output.
Также предоставляет параметр $return_var, который содержит код ошибки/код выхода из запущенного приложения или оболочки. Вы можете получить:
- ENOENT (2) — Нет такого файла
- EIO (127) — Ошибка ввода-вывода: файл не найден
// выполнение команды, сопряженный с stderr, output + код ошибки
var_dump(exec(«ffmpeg -h 2>&1», $output, $errno), $output, $errno));
shell_exec()— это то, что вы хотите запускать в основном для выражений в стиле shell.
Обязательно назначьте/распечатайте возвращаемое значение, например, так: var_dump(shell_exec(«…»));`встроенные обратные кавычки → идентичны shell_exec.
system()— аналогичен exec, но всегда возвращает результат как результат функции. Дополнительно позволяет фиксировать код результата.
passthru()— еще одна альтернатива exec, но всегда отправляет любые результаты в STDOUT (выходной буфер PHP). Это часто делает его наиболее подходящей альтернативой exec.
popen() или лучше proc_open()— разрешает отдельно захватывать STDOUT и STDERR.
Большинство ошибок оболочки попадают в журнал ошибок PHP или Apache, если их не перенаправить. Проверьте свой системный журнал или журнал Apache, если ничего не дает полезных сообщений об ошибках.
Наиболее распространенные проблемы:
Для устаревших тарифных планов веб-хостинга все еще может быть включен safe_mode или disable_functions. Ни одна из функций PHP exec не будет работать (лучше всего найти лучшего провайдера, иначе изучите «CGI» — но не устанавливайте свой собственный интерпретатор PHP, пока не разберетесь).
Точно так же иногда могут быть установлены AppArmor/SELinux/Firejail. Они ограничивают способность каждого приложения порождать новые процессы.
Предполагаемый двоичный файл не существует. Практически ни у одного веб-хоста нет предустановленных инструментов вроде ffmpeg. Вы не можете просто запускать произвольные команды shell без подготовки. Некоторые вещи должны быть установлены!
PATH отключен. Если вы установили пользовательские инструменты, вам нужно убедиться, что они доступны. Использование var_dump(shell_exec(«ffmpeg -opts»)) выполнит поиск по всем общим путям, или как было сказано/ограничено Apache (часто только /bin:/usr/bin).
Проверьте с помощью print_r($_SERVER);, что содержит ваш PATH и покрывает ли он инструмент, который вы хотели запустить. В противном случае вам может понадобиться изменить настройки сервера (/etc/apache2/envvars) или использовать полные пути:
// запуск с абсолютными путями к двоичным файлам
var_dump(shell_exec(«/bin/sh -c ‘/usr/local/bin/ffmpeg -opts 2>&1′»));
Это в некоторой степени подрывает концепцию shell. Лично я не считаю это предпочтительным. Однако это имеет смысл в целях безопасности; более того, конечно, при использовании пользовательских установок.
Дополнительно:
Для того чтобы запустить двоичный файл в системе BSD/Linux, его необходимо сделать «исполняемым». Именно это делает chmod a+x ffmpeg.
Кроме того, путь к таким пользовательским двоичным файлам должен быть доступен для чтения пользователю Apache, под которым работают ваши PHP-скрипты.
Более современные установки используют встроенный в PHP режим FPM (suexec+FastCGI), где учетная запись вашего хостинга равна той, под которой работает PHP.
Протестируйте с помощью SSH. Это само собой разумеется, но прежде чем выполнять команды через PHP, было бы разумно протестировать его в реальной оболочке. Проверьте, например, ldd ffmpeg, есть ли все lib-зависимости и работает ли он в противном случае.
Используйте namei -m /Usr/local/bin/ffmpeg для проверки всего пути, если не уверены, что могут возникнуть проблемы с разрешением доступа.
Входные значения (GET, POST, имена ФАЙЛОВ, данные пользователя), передаваемые в качестве аргументов команд в строках exec, должны быть экранированы с помощью escapeshellarg().
$q = «escapeshellarg»;
var_dump(shell_exec(«echo {$q($_GET[‘text’])} | wc»));
Следите за тем, чтобы не комбинировать обратные символы с любой из функций *exec():
$null = shell_exec(`wc file.txt`);
Обратные символы выполнят команду и оставят shell_exec с выводом уже выполненной команды. Используйте обычные кавычки для обертывания параметра команды.
Также проверьте в сеансе shell, как предполагаемая программа работает с другой учетной записью:
sudo -u www-data gpg –k
В частности для PHP-FPM проверяйте с соответствующим идентификатором пользователя. www-data/apache в основном используются только в старых настройках mod_php.
Многие инструменты cmdline зависят от некоторой конфигурации для каждого пользователя. Этот тест часто показывает, чего не хватает.
Вы не можете получить вывод для фоновых процессов, запущенных с помощью … & или nohup ….. В таких случаях вам определенно нужно использовать перенаправление файла журнала exec(«cmd > log.txt 2>&1 &»);
Ниже приведена команда, которую я безуспешно пытался выполнить:
exec('ln -s ' . PLUGIN_DIR . '/.htaccess ' . ABSPATH . '/.htaccess');
Когда вы добавляете die () в конце, он обнаруживает ошибку:
exec('ln -s ' . PLUGIN_DIR . '/.htaccess ' . ABSPATH . '/.htaccess') or die('what?!');
Для приведенного выше оператора exec () проблема с разрешениями вызывает ошибку, но PHP ее не отображает. Как вы показываете с помощью PHP, какая ошибка происходит?
7 ответы
Вы можете получить результат вывода функция exec передав необязательный второй параметр:
exec('ln -s ' . PLUGIN_DIR . '/.htaccess ' . ABSPATH . '/.htaccess',$output);
var_dump($output);
ответ дан 15 окт ’20, 01:10
Следующий код захватит как нормальный вывод (из StdOut), так и вывод ошибки (из SdtErr).
exec('ln -s ' . PLUGIN_DIR . '/.htaccess ' . ABSPATH . '/.htaccess' . '2>&1',$output);
var_dump($output);
ответ дан 27 окт ’16, 21:10
Параметр $ output не работает, если вызывающая программа передает вывод в STDERR.
Лучший способ справиться с этим — перенаправить вывод из exec в файл, а затем отобразить содержимое этого файла в случае возникновения ошибки.
Если $ cmd содержит команду exec, добавьте что-то вроде этого:
$cmd.=" > $error_log 2>&1"
Затем изучите содержимое спецификации файлов в $ error_log для получения подробной информации о том, почему команда не удалась.
Также обратите внимание, что если вы отключите это с помощью & в конце команды, немедленная проверка содержимого $ error_log может не выявить информацию журнала — сценарий может проверить / обработать файл до завершения работы ОС.
Создан 06 июн.
У меня это сработало в нескольких сценариях:
ob_start();
exec($cmd . " 2>&1", $output);
$result = ob_get_contents();
ob_end_clean();
var_dump($output);
Пространство между «2 Важно
ответ дан 07 авг.
ответ дан 23 мая ’17, 11:05
Если вы не нашли ошибку с помощью этого второго параметра, вы можете найти журнал ошибок apache, например, в Ubuntu Server 12.10 с помощью команды $ tail /var/log/apache2/error.log Я запускал скрипт python из php, ошибка которого была только напечатана там, и, следовательно, я смог ее диагностировать. С наилучшими пожеланиями.
ответ дан 01 дек ’12, 23:12
Это не прямой ответ на ваш вопрос, но очень полезно, если вы хотите знать, что именно произошло, по возвращенному коду ошибки.
Если код ошибки ($ res) возвращается командой:
exec('command', $out, $res);
было в диапазоне 1-2, 126-165, 255, чем было возвращено оболочкой (например, BASH), вызванной из PHP (для выполнения вашей команды). Если возвращаемый код не входит в этот диапазон, значит, он был возвращен вашей командой (не оболочкой).
См. (Описания кодов ошибок BASH)
https://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/exitcodes.html
Создан 18 июля ’18, 12:07
Не тот ответ, который вы ищете? Просмотрите другие вопросы с метками
php
shell
exec
or задайте свой вопрос.
exec
(PHP 4, PHP 5, PHP 7)
exec — Исполняет внешнюю программу
Описание
string exec
( string $command
[, array &$output
[, int &$return_var
]] )
Список параметров
-
command -
Команда (имя программы с аргументами — прим.пер.), которая будет исполнена.
-
output -
Если параметр
outputуказан, то
массив будет заполнен строками вывода программы.
Завершающие пробелы, такие как n (перевод строки — прим.пер.),
включены в массив не будут. Обратите внимание, что если массив уже содержит
какие-либо элементы перед вызовом функции exec(), то
вывод команды будет дописан в конец массива. Если
же вы не хотите дополнять предыдущее содержимое массива, следует вызвать
функцию unset() с именем массива в качестве аргумента
перед его передачей в качестве аргумента функции exec(). -
return_var -
Если заданы оба параметра
return_varи
output, то при выходе эта
переменная будет содержать статус завершения внешней программы.
Возвращаемые значения
Последняя строка вывода при исполнении заданной команды. Если требуется
исполнить команду и получить все данные программы обратно без какой-либо
обработки, следует использовать функцию passthru().
Для получения вывода исполняемой программы, убедитесь, что параметр
output инициализирован и используется.
Примеры
Пример #1 Пример функции exec()
<?php
// выводит имя пользователя, от имени которого запущен процесс php/httpd
// (применимо к системам с командой "whoami" в системном пути)
echo exec('whoami');
?>
Примечания
Внимание
Если вы собираетесь передавать функции
пользовательские данные, используйте функции
escapeshellarg() или escapeshellcmd()
для того, чтобы пользователи не смогли обмануть систему, запустив произвольную команду.
Замечание:
Если вы собираетесь использовать эту функцию
в программе, работающей в качестве демона, убедитесь, что стандартный вывод
функции направлен в файл или другой поток, в противном случае PHP зависнет вплоть
до конца выполнения программы.
Замечание: В случае работы в
безопасном режиме, вы можете запускать что-либо только в пределах
safe_mode_exec_dir.
В настоящее время по практическим причинам запрещено использование .. в качестве компонента пути
к исполняемому файлу.
Смотрите также
- system() — Выполняет внешнюю программу и отображает её вывод
- passthru() — Выполняет внешнюю программу и отображает необработанный вывод
- escapeshellcmd() — Экранирует метасимволы командной строки
- pcntl_exec() — Executes specified program in current process space
- backtick operator
Вернуться к: Функции запуска программ
exec
(PHP 4, PHP 5, PHP 7, PHP 8)
exec-Выполнить внешнюю программу
Description
exec(string $command, array &$output = null, int &$result_code = null): string|false
exec () выполняет данную command .
Parameters
-
command -
Команда,которая будет выполнена.
-
output -
Если аргумент
outputприсутствует, то указанный массив будет заполнен каждой строкой вывода команды. Завершающие пробелы, такие какn, в этот массив не включаются. Обратите внимание, что если массив уже содержит некоторые элементы, exec () добавится в конец массива. Если вы не хотите, чтобы функция добавляла элементы, вызовите unset () для массива перед передачей его в exec () . -
result_code -
Если аргумент
result_codeприсутствует вместе сoutputаргументом, то статус возврата выполненной команды будет записан в эту переменную.
Return Values
Последняя строка результата выполнения команды. Если вам нужно выполнить команду, и все данные из команды будут переданы обратно без каких-либо помех, используйте функцию passthru () .
В случае ошибки возвращает false .
Чтобы получить результат выполненной команды, обязательно установите и используйте output параметр.
Examples
Пример # 1 Exec () Пример
<?php $output=null; $retval=null; exec('whoami', $output, $retval); echo "Returned with status $retval and output:n"; print_r($output); ?>
Из приведенного выше примера будет выведено нечто подобное:
Returned with status 0 and output: Array ( [0] => cmb )
Notes
Warning
При разрешении передачи пользовательских данных в эту функцию используйте функции escapeshellarg () или escapeshellcmd (), чтобы пользователи не могли обманом заставить систему выполнить произвольные команды.
Note:
Если программа запускается с этой функцией,то для продолжения ее работы в фоновом режиме вывод программы должен быть перенаправлен в файл или другой выходной поток.В противном случае PHP зависает до окончания выполнения программы.
Note:
В Windows exec () сначала запустит cmd.exe для запуска команды. Если вы хотите запустить внешнюю программу без запуска cmd.exe, используйте proc_open () с
bypass_shellопцией bypass_shell .
See Also
- system () — Выполнить внешнюю программу и отобразить результат
- passthru () — Запускает внешнюю программу и отображает необработанный вывод
- escapeshellcmd () — Исключает метасимволы оболочки
- pcntl_exec () — Выполняет указанную программу в текущем пространстве процесса
- backtick operator
exec
(PHP 4, PHP 5, PHP 7)
exec — Выполнить внешнюю программу
Описание
exec
( string $command
, array &$output = null
, int &$result_code = null
) : string|false
Список параметров
-
command -
Команда, которая будет исполнена.
-
output -
Если параметр
outputуказан, то
массив будет заполнен строками вывода программы.
Завершающие пробелы, такие какn,
не будут включены в массив. Обратите внимание, что если массив уже содержит
какие-либо элементы, то exec() добавит новые элементы в конец массива.
Если же вы не хотите, чтобы функция добавляла новые элементы в конец, вызовите
unset() на этом массиве, прежде чем передать его в exec(). -
result_code -
Если аргумент
result_codeприсутствует вместе с
output, тогда статус возврата выполненной команды
будет записан в этой переменной.
Возвращаемые значения
Последняя строка из результата команды. Если требуется
выполнить команду и получить все данные команды без какой-либо
обработки, используйте функцию passthru().
Возвращает false в случае возникновения ошибки.
Для получения результата выполнения команды, убедитесь, что параметр
output инициализирован и используется.
Примеры
Пример #1 Пример функции exec()
<?php
// выводит имя пользователя, от имени которого запущен процесс php/httpd
// (применимо к системам с командой "whoami" в системном пути)
$output=null;
$retval=null;
exec('whoami', $output, $retval);
echo "Вернет статус $retval и значение:n";
print_r($output);
?>
Результатом выполнения данного примера
будет что-то подобное:
Вернет статус 0 и значение:
Array
(
[0] => cmb
)
Примечания
Внимание
Если вы собираетесь передавать функции пользовательские данные, используйте функции escapeshellarg() или escapeshellcmd() для того, чтобы пользователи не смогли обмануть систему, запустив произвольную команду.
Замечание:
Если вы собираетесь использовать эту функцию в программе, работающей в качестве демона, убедитесь, что стандартный вывод функции направлен в файл или другой поток, в противном случае PHP зависнет вплоть до конца выполнения программы.
Замечание:
В Windows функция exec() стартует cmd.exe для запуска команды. Если
вы хотите запустить внешнюю программу без запуска cmd.exe, то используйте
функцию proc_open() с установленной опцией
bypass_shell.
Смотрите также
- system() — Выполнить внешнюю программу и отобразить вывод
- passthru() — Выполнить внешнюю программу и отобразить необработанный вывод
- escapeshellcmd() — Экранировать метасимволы командной строки
- pcntl_exec() — Запустить указанную программу в области текущего процесса
- Оператор исполнения