Documentation on shell_exec

shell_exec = Execute command via shell and return the complete output as a string

This function is identical to the backtick operator.

cmd The command that will be executed.

Usage, params, and more on shell_exec

string shell_exec ( string $cmd )

cmd The command that will be executed.

The output from the executed command or NULL if an error occurred or the command produces no output.

Notes and warnings on shell_exec

Basic example of how to use: shell_exec

Example #1 A shell_exec() example

<?php
$output 
shell_exec('ls -lart');
echo 
"<pre>$output</pre>";
?>

Other code examples of shell_exec being used

I'm not sure what shell you are going to get with this function, but you can find out like this:

<?php
$cmd
= 'set';
echo
"<pre>".shell_exec($cmd)."</pre>";
?>

On my FreeBSD 6.1 box I get this:

USER=root
LD_LIBRARY_PATH=/usr/local/lib/apache2:
HOME=/root
PS1='$ '
OPTIND=1
PS2='> '
LOGNAME=root
PPID=88057
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin
SHELL=/bin/sh
IFS='    
'

Very interesting.  Note that the PATH may not be as complete as you need.  I wanted to run Ghostscript via ImageMagik's "convert" and ended up having to add my path before running the command:

<?php
$cmd
= 'export PATH="/usr/local/bin/"; convert -scale 25%x25% file1.pdf[0] file2.png 2>&1';
echo
"<pre>".shell_exec($cmd)."</pre>";
?>

ALSO, note that shell_exec() does not grab STDERR, so use "2>&1" to redirect it to STDOUT and catch it.

RE: kamermans note,

I was having a similar problem with the PATH variable when using shell_exec. Even with a hard-coded full path to a binary, I also got an error about a .so file that could not be found. After some reading up, I realized I had to set the LD_LIBRARY_PATH variable:

<?php

$command
= 'export LD_LIBRARY_PATH="' . $path_to_library_dir .'"; ' . $path_to_binary;
shell_exec($command);

?>

Hope this saves someone a headache,

- G

Also after lots of hair pulling why shell_exec didn't want to work for me I found out that in my case some things needed to be set (which normally are set by default).

the options -jo 
-j means: don't recreate the paths found in the archive
-o means: always overwrite files

And I needed to specify the destination path (even though it should unzip in the same directory when not specified), this is done by -d [path]

The strange thing was that I didn't have to put these options when I would give the command on the command-line, only when I would call it with shell_exec.

So the complete command in php would be for me:

shell_exec('unzip -jo /path_to_archive/archive.zip  -d /destination_path')

And putting en echo in front will help you a lot.
it should tell you something like this:
    

Archive:  /path_to_zip/archive.zip
  inflating: /destination_path/file1.jpeg 
  inflating: /destination_path/file2.jpeg
  inflating: /destination_path/file3.jpeg

I have PHP (CGI) and Apache. I also shell_exec() shell scripts which use PHP CLI. This combination destroys the string value returned from the call. I get binary garbage.  Shell scripts that start with #!/usr/bin/bash return their output properly.

A solution is to force a clean environment.  PHP CLI no longer had the CGI environment variables to choke on.

<?php

// Binary garbage.
$ExhibitA = shell_exec('/home/www/myscript');

// Perfect.
$ExhibitB = shell_exec('env -i /home/www/myscript');

?>

-- start /home/www/myscript
#!/usr/local/bin/phpcli
<?php

echo("Output.\n");

?>
-- end /home/www/myscript

I've write a Full Class for Run in Background, Kill PID , check if is Running

<?php
/**
* @author     Ashraf M Kaabi
* @name       Advance Linux Exec
*/
class exec {
   
/**
     * Run Application in background
     *
     * @param     unknown_type $Command
     * @param     unknown_type $Priority
     * @return     PID
     */
   
function background($Command, $Priority = 0){
       if(
$Priority)
          
$PID = shell_exec("nohup nice -n $Priority $Command > /dev/null & echo $!");
       else
          
$PID = shell_exec("nohup $Command > /dev/null & echo $!");
       return(
$PID);
   }
  
/**
    * Check if the Application running !
    *
    * @param     unknown_type $PID
    * @return     boolen
    */
  
function is_running($PID){
      
exec("ps $PID", $ProcessState);
       return(
count($ProcessState) >= 2);
   }
  
/**
    * Kill Application PID
    *
    * @param  unknown_type $PID
    * @return boolen
    */
  
function kill($PID){
       if(
exec::is_running($PID)){
          
exec("kill -KILL $PID");
           return
true;
       }else return
false;
   }
};
?>

Here is a easy way to grab STDERR and discard STDOUT:
    add  '2>&1 1> /dev/null' to the end of your shell command

For example:
<?php
$output
= shell_exec('ls file_not_exist 2>&1 1> /dev/null');
?>

it took me a heck of a lot of head banging to finally solve this problem so I thought that I would mention it here.

If you are using Eclipse and you try to do something like

<?php

    $out
= shell_exec("php -s $File");   //this fails
?>

it will always fail when run inside of the Eclipse debugger.  This happens on both Linux and Windows.  I finally isolated the problem to changes that Eclipse makes to the environment when debugging.  

The fix is to force the ini setting.  If you don't need an ini then -n is sufficient.

<?php
   
    $out
= shell_exec("php -n -s $File");   //this works
?>

Of course if you run it outside of the debugger then it works fine without the -n.   You may want to use a debug flag to control this behavior.

The Subversion error "svn: Can't recode string" can be caused by the locale being wrong.  Try
<?php
putenv
('LANG=en_US.UTF-8');
?>
(or whatever your preferred locale is) before you call shell_exec()

If you need to execute a command without permission and could not execute it by ssh or install any extension, there is a way in Apache 1.3.x and PHP 4.
Create a file on cgi-bin directory, like this:

#!/usr/bin/php
<?
  echo shell_exec('whoami');
?>

Don't forget to set the file you created the permission to execute it. Hence, call it from browser and you will se that this script will be executed by the shell user and not the user nobody (apache default user if running a PHP script).

For capturing stdout and stderr, when you don't care about the intermediate files, I've had better results with . . .
<?php
function cmd_exec($cmd, &$stdout, &$stderr)
{
   
$outfile = tempnam(".", "cmd");
   
$errfile = tempnam(".", "cmd");
   
$descriptorspec = array(
       
0 => array("pipe", "r"),
       
1 => array("file", $outfile, "w"),
       
2 => array("file", $errfile, "w")
    );
   
$proc = proc_open($cmd, $descriptorspec, $pipes);
   
    if (!
is_resource($proc)) return 255;

   
fclose($pipes[0]);    //Don't really want to give any input

   
$exit = proc_close($proc);
   
$stdout = file($outfile);
   
$stderr = file($errfile);

   
unlink($outfile);
   
unlink($errfile);
    return
$exit;
}
?>

This isn't much different than a redirection, except it takes care of the temp files for you (you may need to change the directory from ".") and it blocks automatically due to the proc_close call.  This mimics the shell_exec behavior, plus gets you stderr.

<?php

/**
* PHP Kill Process
*
* Sometimes, it can happen a script keeps running when it shouldn't, and it
* won't stop after we close the browser, or shutdown the computer. Because it's
* not always easy to use SSH there's a workaround.
*
* @author      Jensen Somers <php@jsomers.be>
* @version     1.0
*/

class KillAllProcesses {
   
/**
     * Construct the class
     */
   
function killallprocesses() {
       
$this->listItems();
    }
   
   
/**
     * List all the items
     */
   
function listItems() {
       
/*
         * PS   Unix command to report process status
         * -x   Select processes without controlling ttys
         *
         * Output will look like:
         *      16479 pts/13   S      0:00 -bash
         *      21944 pts/13   R      0:00 ps -x
         *
         */
       
$output =   shell_exec('ps -x');
       
       
$this->output($output);
       
       
// Put each individual line into an array
       
$array  =   explode("\n", $output);
       
       
$this->doKill($array);
    }
   
   
/**
     * Print the process list
     * @param   string  $output
     */
   
function output($output) {
        print  
"<pre>".$output."</pre>";
    }
   
   
/**
     * Kill all the processes
     * It should be possible to filter in this, but I won't do it now.
     * @param   array   $array
     */
   
function doKill($array) {
       
/*
         * Because the first line of our $output will look like
         *        PID TTY      STAT   TIME COMMAND
         * we'll skip this one.
         */
       
for ($i = 1; $i < count($array); $i++) {
           
$id =   substr($array[$i], 0, strpos($array[$i], ' ?'));
           
shell_exec('kill '.$id);
        }
    }
}

new
KillAllProcesses();

?>

It's not the very best solution, but I've used it a couple of times when I needed to do it quick without to much trouble.
Make not I kill all the processes, on my server px -x will only return like 4 times /sbin/apache and it's pretty safe to kill them without any trouble.

To run a command in background, the output must be redirected to /dev/null. This is written in exec() manual page. There are cases where you need the output to be logged somewhere else though. Redirecting the output to a file like this didn't work for me:

<?php
# this doesn't work!
shell_exec("my_script.sh 2>&1 >> /tmp/mylog &");
?>

Using the above command still hangs web browser request.

Seems like you have to add exactly "/dev/null" to the command line. For instance, this worked:

<?php
# works, but output is lost
shell_exec("my_script.sh 2>/dev/null >/dev/null &");
?>

But I wanted the output, so I used this:

<?php
shell_exec
("my_script.sh 2>&1 | tee -a /tmp/mylog 2>/dev/null >/dev/null &");
?>

Hope this helps someone.