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:

Be careful as to how you elevate privileges to your php script. It's a good idea to use caution and planing. It is easy to open up huge security holes. Here are a couple of helpful hints I've gathered from experimentation and Unix documentation.

Things to think about:

1. If you are running php as an Apache module in Unix then every system command you run is run as user apache. This just makes sense.. Unix won't allow privileges to be elevated in this manner. If you need to run a system command with elevated privileges think through the problem carefully!

2. You are absolutely insane if you decide to run apache as root. You may as well kick yourself in the face. There is always a better way to do it.

3. If you decide to use a SUID it is best not to SUID a script. SUID is disabled for scripts on many flavors of Unix. SUID scripts open up security holes, so you don't always want to go this route even if it is an option. Write a simple binary and elevate the privileges of the binary as a SUID. In my own opinion it is a horrible idea to pass a system command through a SUID-- ie have the SUID accept the name of a command as a parameter. You may as well run Apache as root!

On Windows, if shell_exec does NOT return the result you expected and the PC is on an enterprise network, set the Apache service (or wampapache) to run under your account instead of the 'Local system account'. Your account must have admin privileges.

To change the account go to console services, right click on the Apache service, choose properties, and select the connection tab.

A simple way to handle the problem of capturing stderr output when using shell-exec under windows is to call ob_start() before the command and ob_end_clean() afterwards, like this:

<?phpob_start()$dir = shell_exec('dir B:');if is_null($dir){ // B: does not exist // do whatever you want with the stderr output here}else{ // B: exists and $dir holds the directory listing // do whatever you want with it here}ob_end_clean(); // get rid of the evidence :-)?>

If B: does not exist then $dir will be Null and the output buffer will have captured the message:

'The system cannot find the path specified'.

(under WinXP, at least). If B: exists then $dir will contain the directory listing and we probably don't care about the output buffer. In any case it needs to be deleted before proceeding.

As far as error checking on the last example. Several of the shells have the && operator, so you just string your commands together using it instead of ; If at any time any of the programs fail, you will return without running the rest

Just a quick reminder for those trying to use shell_exec on a unix-type platform and can't seem to get it to work. PHP executes as the web user on the system (generally www for Apache), so you need to make sure that the web user has rights to whatever files or directories that you are trying to use in the shell_exec command. Other wise, it won't appear to be doing anything.

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.

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:

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.

We assume in this case if the script produces output it has ran ok, the $out variable will then contain the output, if $out is empty then we read the captured error output from a file simply called 'output'.

With PHP on Windows, if you get the 'Warning: shell_exec() [function.shell-exec]: Unable to execute' error, then you need to check the permissions on file 'C:\WINDOWS\system32\cmd.exe'. You need read/execute permission on this file. I would recommend using the sysinternals Process Monitor 'procmon.exe' to confirm the user that is trying to run 'cmd.exe'. Filter on 'Process Name' is 'php-cgi.exe' and 'Path' ends with 'cmd.exe'. Look at the event properties for the task with the access denied error, and it will show you the 'Impersonating' user name. This is usually the 'Internet Guest Account', often 'NT AUTHORITY\IUSR'.

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).

Interestingly, if you execute a script which is not in your path (or you have made a typo, or if the script does no exist at all), you will get no return value. The error will be logged into the error_log of your webserver.

Someone could add a note how this can be (if it could be) overriden, as the standard behaviour is not really fool-proof.

/** * 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 */

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.

The technique mentioned by Nathan De Hert below is rather insecure -- you should never leave a password lying around in a file readable by the apache user.

If you need this sort of functionality on *nix systems, have a look at the /etc/sudo file (edited with the command 'visudo'). The tag NOPASSWD allows specified commands to be run as root by another user, without needing to specify a password. It's a little extra configuration, but much more secure.

When following Kenneth's method for executing root scripts via the nanoweb server mentioned on this page you would most likely need to be able to run a text-mode browser like lynx and pass the php script to it (works great).

After struggling for a while (lynx kept asking me to download the file instead of executing it), I realised that I had to install php-cgi additionally and modify the nanoweb config file to use that php interpreter instead of /usr/bin/php. (On Debian this is the CLI version).

On Ubuntu 6.06:

apt-get install php5-cgi

After editing /etc/nanoweb/nanoweb.conf and a quick restart of the web server, lynx and links will execute your PHP scripts properly.

Got it! That was a "how does the windows scripting host work" problem.Here's the answer:<?php$runCommand = "C:\\WINDOWS\\system32\\shutdown.exe -t:30"; //Wrong by purpuse to get some good output$WshShell = new COM("WScript.Shell");$output = $WshShell->Exec($runCommand)->StdOut->ReadAll;echo "<p>$output</p>";?>

I don't know how it goes in Windows, but in Linux, shell returns result with a line break at the end, I guess to make it more readable in shell, so don't forget to use trim() to encapsulate the returned result!

regarding the "ping" test that was mentioned by andy25it at hotmail dot it:

this might not work if the target server is behind a firewall which drops icmp packets. a better approach would be the use of fsockopen(), which doesn't use icmp. in the notes section of the function list, Alexander Wegener wrote a nice implementation of an isOnline() function which works with both http and https.

When running subprocesses via shell_exec (and maybe others) from Apache/mod_php4, Apache's environment variables don't seem to be passed on to the subprocess environment unless you specifically force them by using putenv something like this:

After many failed attempts to find a way to run a php script in the background (the script had to be activated from a web browser). Since I create and test my scripts on a windows box, I need an automatic way to detect if the script was running on windows or the Linux server. The activated script will continue to run even if you close your browser.

If someone has problems with IIS6 and CGI error message "The specified CGI application misbehaved by not returning a complete set of HTTP headers.", simply make sure that headers are already sent:echo "<head>";flush();$result = shell_exec('C:\util\myprog.exe');

Run shell_exec powershell on IIS 7, PHP-Fast-CGI:First of all, make sure you have set TPC protocol in IIS FastCGI Settings.Next you can run shell_exec command as:$output = shell_exec('powershell get-process < NUL');echo $output;Hope this help.

The key is the "--login" option which appends all the required common cygwin binary and library paths to $PATH. Without this option some of the cygwin binaries that links to other libraries ( Like ImageMagick binaries which links to X11 ) will not work and you may see errors like "cygX11-6.dll not found, Could not start convert.exe"

//wish this could help for handle the shell_exec() output strings where "\n" that looks like a " " space.//ex:$configPath = "/home/somewhere";$configList = shell_exec("ls $configPath/123.*.cfg"); // output is "/home/somewhere/123.111.cfg /home/somewhere/123.112.cfg"// there looks like a "space" between output strings, but that's a "\n" actually.$nodeList = trim(str_replace("\n",",",str_replace("$configPath/","",str_replace(".cfg","",$configList)))); // get "123.111,123.112"

Got the error "Unable to execute..." when trying to run an external program with shell_exec under Windows XP, IIS 5, php 4.3.7 Solved by giving the IIS user (IUSR_...) execution privileges on the system file %systemroot%\system32\cmd.exe This should be used carefully because may represent a server's security hole.

The problem described by 'concept at conceptonline dot hu' was mine too (writing the output on the Apache error log instead of returning it). But I think the cause explanation is misleading: it is not due to running script in a different path. The clue for this behaviour as Apache documentation mention is:

"A very wide variety of different messages can appear in the error log. Most look similar to the example above. The error log will also contain debugging output from CGI scripts. Any information written to <i>stderr</i> by a CGI script will be copied directly to the error log." (http://httpd.apache.org/docs/1.3/logs.html#errorlog)

So the most probable cause for this problem is a running script which tends to write its output on stderr instead of stdout. You cannot even capture it by piping (e.g. [command]>[output] syntax of unix).The smart trick to get rid of this situation (that can become a serious one as I experienced) is one suggested by Anatol Pomozov in his currently non-accessible weblog (I saw his post on archive.com!):You should add after your command these characters within the qoutation mark:" 2>&1"I guess it forces OS to copy stderr on stdout.

Sometimes it's needed to be able to execute shell commands as root using PHP. For instance, restarting named after adding or changing zones, or adding new alliases for sendmail.

My approach is to run a server called Nanoweb, available from http://nanoweb.si.kz/. It's a webserver written in PHP, and needs only the pcntl extension extra to operate. Nanoweb is configured to only listen for connections on localhost, port 81 for example. From my normal PHP scripts running inside Apache I simply call scripts in Nanoweb to get the messy 'root' tasks done. Much more secure and safer.

For those running PHP on IIS under a 64-bit system, but running IIS in 32-bit mode, you will need to grant the IUSR_<machinename> user Read & Execute / Read permissions not on the C:\WINDOWS\SYSTEM32\cmd.exe file, but instead on the C:\WINDOWS\SysWOW64\cmd.exe - which is the 32-bit version of the command prompt.

(if you have any other way of doing this PLEASE send me a mail)(The following note is interesting to *NIX administrators ONLY)Jailing a PHP CLI session is not the easiest thing to do.

PHP has a gigantic list of dependencies, you can check it byldd `which php`Each of these .so files (shared libraries) can have dependencies, and can depend on each other, making the list much bigger.However, there are tools out there to copy all dependencies into a jailed directory, you just have to search for them - and I had no luck.

her's a function that is similar to shell_exec but captures both stdout and stderr. It's much more complicated than using 2>&1, but it's independent of the shell and should work on windows, too. It uses proc_open with stream_select and non-blocking streams to read stdout and stderr concurrently. It is not guarantied that the lines appear in the correct order or that they are not intermingeled - but it did not happened when I tested it. So, here goes:

Note that whatever you run with this function seems to use PHP memory, so it will die if it exceeds the limit (usually 8 megs) To do database dumps or other memory-hogging operations use something like system() instead.

Just a note for anybody who's box is involuntarily running in safemode (i.e. you buy space on a server), or just not working right. Shell commands won't work. You can, however, use PHPs FTP functions to FTP in. I was copying files and making directories, but I assume there might be a way to do something more complex.

If you're running scripts or commands and can't figure out what's not working, check to make sure that you're not using an alias in place of a command. PHP (quite reasonably) doesn't seem to recognise aliases.

Now depending if your root or not some commands like "make install" may fail. This doesn't do any error checking, the reason for that is I do not know how to cd to a directory and then execute another command unless they are in the same shell.

So basically, take what you type on the command line and string them together.

If you're on a host that provides neither shell access nor a way to unzip uploaded archives, you can use PHP to call the unzip utility with shell_exec() (provided they're not also running in safe mode). Just make sure that PHP has write permission to the destination directory, or it won't work.

Here's an example script that accomplishes this, which you're free to use if you so chose:

In response to nathandehert and Paul Cook, rather than sudoing to execute a command, you might want to abstract the command(s) into a yet another script (php, perl, bash, whatever) and make use of the setuid bit. then just execute that script from php. of course, bear in mind the security implications of setuid.

Running PHP 4.2.3 on Windows 2000 Server shell_exec works fine and passes its output to the variable when the result of the executed command is true. However, if the command fails and the DOS-shell returns an error the result is no longer availiable in the variable but is passed directly to the page.