getting output and exit status from shell_exec()
As you've already seen, when using shell_exec you have to chain your "real" command with echo $? to get the exit status:
$output_including_status = shell_exec("command 2>&1; echo $?");
but if you want the clean way, then you want to use the exec function, which allows a 3rd agument explicitly for this purpose.
PHP reading shell_exec live output
To read the output of a process, popen()
is the way to go. Your script will run in parallel with the program and you can interact with it by reading and writing it's output/input as if it was a file.
But if you just want to dump it's result straight to the user you can cut to the chase and use passthru()
:
echo '<pre>';
passthru($cmd);
echo '</pre>';
If you want to display the output at run time as the program goes, you can do this:
while (@ ob_end_flush()); // end all output buffers if any
$proc = popen($cmd, 'r');
echo '<pre>';
while (!feof($proc))
{
echo fread($proc, 4096);
@ flush();
}
echo '</pre>';
This code should run the command and push the output straight to the end user at run time.
More useful information
Note that if you are using sessions then having one of those running will prevent the user from loading other pages, as sessions enforce that concurrent requests cannot happen. To prevent this from being a problem, call session_write_close()
before the loop.
If your server is behind a nginx gateway, then the nginx buffering may be disruptive to the desired behavior. Set the header header('X-Accel-Buffering: no');
to hint nginx that it shouldn't do that. As headers are sent first, this has to be called in the beginning of the script, before any data is sent.
PHP system(), exec(), and shell_exec() not returning output
I think that the issue is not that you not get the output of the executed command, but which
fails to find mysql
.
Using exec
you can get the return status of your command, where 0
means successful, and other values indicate an error.
$output = exec($cmd, $output, $retval);
var_dump($output);
var_dump($retval);
If the $retval
is 1
that would mean which
doesn't find the mysql
binary, and returns an empty line.
php system command with output and return code
Sounds like you're looking for output buffering:
ob_start();
system($command, $returnCode);
$output = ob_get_clean();
This should preserve all white-space characters at the end of each output line (exec
as you wrote destroys these, so implode
would not be an option).
Alternatively, you can open a process and aquire the pipes (standard output, STDOUT) and read the output out of these. But it's more complicated (but gives you more options). See proc_open
.
Running shell_exec() in background AND getting its output afterwards
Solution for a similar problem: A few years ago I had a similar problem. I had to upload a file to a FTP server. I wondered how to communicate to the FTP server that the file was uploaded completely, so that the FTP server can perform some tasks on it. My solution was to rename the file to something like *.completed after it was uploaded completely. Then the process on the FTP server could look for *.completed files only.
Solution adjusted to your problem: I'd suggest you to rename your temp file after it was generated by your bash script. This way you can independently find out if the script was executed successfully.
shell_exec()
could look like this:shell_exec('<myscript> > tmp-file && mv tmp-file tmp-file.completed &');
Be aware that this only redirects the channel STDOUT into the the tmp-file. If you also want to redirect STDERR into the tmp-file, try this:
shell_exec('<myscript> &> tmp-file && mv tmp-file tmp-file.completed &');
Executing program in php - display and return output
Maybe this one will interest you? proc_open()
- http://www.php.net/manual/en/function.proc-open.php
And here is a handy snippet which might work for you (it's copied from the comments on the site I gave you the link to):
<?php
/*
* Execute and display the output in real time (stdout + stderr).
*
* Please note this snippet is prepended with an appropriate shebang for the
* CLI. You can re-use only the function.
*
* Usage example:
* chmod u+x proc_open.php
* ./proc_open.php "ping -c 5 google.fr"; echo RetVal=$?
*/
define(BUF_SIZ, 1024); # max buffer size
define(FD_WRITE, 0); # stdin
define(FD_READ, 1); # stdout
define(FD_ERR, 2); # stderr
/*
* Wrapper for proc_*() functions.
* The first parameter $cmd is the command line to execute.
* Return the exit code of the process.
*/
function proc_exec($cmd)
{
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$ptr = proc_open($cmd, $descriptorspec, $pipes, NULL, $_ENV);
if (!is_resource($ptr))
return false;
while (($buffer = fgets($pipes[FD_READ], BUF_SIZ)) != NULL
|| ($errbuf = fgets($pipes[FD_ERR], BUF_SIZ)) != NULL) {
if (!isset($flag)) {
$pstatus = proc_get_status($ptr);
$first_exitcode = $pstatus["exitcode"];
$flag = true;
}
if (strlen($buffer))
echo $buffer;
if (strlen($errbuf))
echo "ERR: " . $errbuf;
}
foreach ($pipes as $pipe)
fclose($pipe);
/* Get the expected *exit* code to return the value */
$pstatus = proc_get_status($ptr);
if (!strlen($pstatus["exitcode"]) || $pstatus["running"]) {
/* we can trust the retval of proc_close() */
if ($pstatus["running"])
proc_terminate($ptr);
$ret = proc_close($ptr);
} else {
if ((($first_exitcode + 256) % 256) == 255
&& (($pstatus["exitcode"] + 256) % 256) != 255)
$ret = $pstatus["exitcode"];
elseif (!strlen($first_exitcode))
$ret = $pstatus["exitcode"];
elseif ((($first_exitcode + 256) % 256) != 255)
$ret = $first_exitcode;
else
$ret = 0; /* we "deduce" an EXIT_SUCCESS ;) */
proc_close($ptr);
}
return ($ret + 256) % 256;
}
/* __init__ */
if (isset($argv) && count($argv) > 1 && !empty($argv[1])) {
if (($ret = proc_exec($argv[1])) === false)
die("Error: not enough FD or out of memory.\n");
elseif ($ret == 127)
die("Command not found (returned by sh).\n");
else
exit($ret);
}
?>
Related Topics
Does the Order of Class Definition Matter in PHP
Mysqli_Select_Db() Expects Parameter 1 to Be MySQLi, String Given
3Rd Party Dependency Conflict in Developing Wordpress Plugin
Send Email with Attachment Using PHP
How to Reverse Order Output of a MySQL Query
PHP in Background Exec() Function
$Php_Autoconf Errors on MAC Os X 10.7.3 When Trying to Install Pecl Extensions
Storing Datetime as Utc in PHP/Mysql
How to Create and Store Md5 Passwords in MySQL
How to Call a PHP Function from Ajax
Php: Split Multibyte String (Word) into Separate Characters
Fix Incorrectly Displayed Encoding on an HTML Document with PHP
How to Obtain a Nested HTML List from Object's Array Recordset
Cross Domain Ajax Request with Jquery/Php
How to Run the PHP Script at Scheduled Time
How to Configuring a Xampp Web Server for Different Root Directory