For a week, I struggled to execute a Perl script and grab it’s output, all to be done within a PHP program. Finally, after an exhaustive search, I found my savior – “Shell_exec” command in PHP. Although, the “shell_exec” command does exactly what I wanted, the road ahead was full of thorny issues. To help developers in the similar situation as of mine, here I present a structured document on the problems that one might encounter while trying to run “shell_exec” command.
Problem 1: Shell_exec() [function.shell-exec]: Cannot execute….. in Safe Mode:
Solution: In this case, the potential problem might be that your php is running in safe mode. Open php.ini file in a text editor and search for “safe_mode”. Make sure that it is turned off i.e
safe_mode = Off
Restart your webserver and try to run the php program again. "Shell_exec" command should be working now.
Problem 2: Able to execute simple commands such as “cmd”, “cd”, etc., but not perl script
Problem 3: Able to run perl script via command prompt but not using shell_exec
Solution: Problem 2 and 3 are related and, in most cases, are caused by the same problem. In both cases, probably, including the full path of perl.exe might solve the problem of running a perl script. For example
Shell_exec(“perl hello.pl”) // originally I was trying this
Another useful function that might was to consider is runExternal. It was contributed by one of the developers and is available on www.php.net. A copy of the runExternal function is below.
function runExternal($cmd,&$code) {
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a file to write to
);
$pipes= array();
$process = proc_open($cmd, $descriptorspec, $pipes);
$output= "";
if (!is_resource($process)) return false;
#close child's input imidiately
fclose($pipes[0]);
stream_set_blocking($pipes[1],false);
stream_set_blocking($pipes[2],false);
$todo= array($pipes[1],$pipes[2]);
while( true ) {
$read= array();
if( !feof($pipes[1]) ) $read[]= $pipes[1];
if( !feof($pipes[2]) ) $read[]= $pipes[2];
if (!$read) break;
$ready= stream_select($read, $write=NULL, $ex= NULL, 2);
if ($ready === false) {
break; #should never happen - something died
}
foreach ($read as $r) {
$s= fread($r,1024);
$output.= $s;
}
}
fclose($pipes[1]);
fclose($pipes[2]);
$code= proc_close($process);
return $output;
}
?>
here is how to use it:
$result= runExternal("ls -l some-file.txt",$code);
print "";
\n";
print $result;
print "
print "code: $code\n";
?>
As you might already noticed, runExternal command replaces shell_exec. While shell_exec only returns output and no errors, runExternal returns output as well as errors. Thus runExternal is a useful during debugging process.