# shell_exec

(PHP 4, PHP 5, PHP 7)

shell_execExecute command via shell and return the complete output as a string

string shell_exec ( string $cmd ) This function is identical to the backtick operator. ### Parameters cmd The command that will be executed. ### Return Values The output from the executed command or NULL if an error occurred or the command produces no output. Note: This function can return NULL both when an error occurs or the program produces no output. It is not possible to detect execution failures using this function. exec() should be used when access to the program exit code is required. ### Examples Example #1 A shell_exec() example <?php$output
shell_exec('ls -lart');
echo
"<pre>$output</pre>"; ?> ### Notes Note: This function is disabled when PHP is running in safe mode. ### See Also add a note ### User Contributed Notes 70 notes 153 trev at dedicate.co.uk 7 years ago If you're trying to run a command such as "gunzip -t" in shell_exec and getting an empty result, you might need to add 2>&1 to the end of the command, eg: Won't always work: echo shell_exec("gunzip -c -t$path_to_backup_file");

Should work:
echo shell_exec("gunzip -c -t $path_to_backup_file 2>&1"); In the above example, a line break at the beginning of the gunzip output seemed to prevent shell_exec printing anything else. Hope this saves someone else an hour or two. 15 alexandre dot schmidt at gmail dot com 2 years ago 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. Anonymous 13 years ago 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! mcbeth at broggs dot org 15 years ago 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 Rgemini 9 years ago 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: <?php ob_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.
jack dot harris-7ot2j4ip at yopmail dot Com
4 years ago
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.
rustleb at hotmail dot com
12 years ago
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. wally at soggysoftware dot co dot uk 6 years ago As others have noted, shell_exec and the backtick operator () both return NULL if the executed command doesn't output anything. This can be worked around by doing anything like the following: shell_exec ("silentcmd && echo ' '"); Here we're simply outputting blank whitespace if the command succeeds - which satisfies this slightly strange issue. From there, you can trim() the command output etc. eric dot peyremorte at iut-valence dot fr 11 years ago I had trouble with accented caracters and shell_exec. ex : Executing this command from shell : /usr/bin/smbclient '//BREZEME/peyremor' -c 'dir' -U 'peyremor%*********' -d 0 -W 'ADMINISTRATIF' -O 'TCP_NODELAY IPTOS_LOWDELAY SO_KEEPALIVE SO_RCVBUF=8192 SO_SNDBUF=8192' -b 1200 -N 2>&1 gave me that : Vidéos D 0 Tue Jun 12 14:41:21 2007 Desktop DH 0 Mon Jun 18 17:41:36 2007 Using php like that : shell_exec("/usr/bin/smbclient '//BREZEME/peyremor' -c 'dir' -U 'peyremor%*******' -d 0 -W 'ADMINISTRATIF' -O 'TCP_NODELAY IPTOS_LOWDELAY SO_KEEPALIVE SO_RCVBUF=8192 SO_SNDBUF=8192' -b 1200 -N 2>&1") gave me that : Vid Desktop DH 0 Mon Jun 18 17:41:36 2007 The two lines were concatenated from the place where the accent was. I found the solution : php execute by default the command with LOCALE=C. I just added the following lines before shell_exec and the problem was solved :$locale = 'fr_FR.UTF-8';
setlocale(LC_ALL, $locale); putenv('LC_ALL='.$locale);

saivert at saivert dot com
10 years ago
How to get the volume label of a drive on Windows

<?php

function GetVolumeLabel($drive) { // Try to grab the volume name if (preg_match('#Volume in drive [a-zA-Z]* is (.*)\n#i', shell_exec('dir '.$drive.':'), $m)) {$volname = ' ('.$m[1].')'; } else {$volname = '';
}
return
$volname; } print GetVolumeLabel("c"); ?> Note: The regular expression assumes a english version of Windows is in use. modify it accordingly for a different localized copy of Windows. RoBorg 11 years ago 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() jessop <AT> bigfoot <DOT> com 14 years ago 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. codeslinger at compsalot dot com 8 years ago 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. tonysb at gmx dot net 16 years ago shell_exec is extremely useful as a substitute for the virtual() function where unavailable (Microsoft IIS for example). All you have to do is remove the content type string sent in the header: <?$mstrng = shell_exec('yourcgiscript.cgi');
$mstrng = ereg_replace( "Content-type: text/html", "",$mstrng );
echo $mstrng; ?> This works fine for me as a substitute for SSI or the virtual() func. Anton Babadjanov http://www.vbcn.com.ar joelhy 9 years ago 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');
?>
kamermans at teratechnologies dot net
11 years ago
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. gabekon at gmail dot com 10 years ago 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 Martin Rampersad 14 years ago 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 dburles@NOSPAMgmailDOTcom 9 years ago Easy way to capture error output in windows // we'll execute a php script as an example:$out = shell_exec("php test.php 2> output");
print $out ?$out : join("", file("output"));

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

Hope this helps someone
-1
ricky at rocker dot com
1 month ago
despite:

shell_exec("env")

returning

SHELL=/bin/bash

I simply could not get:

shell_exec("bash command <(another bash command)")

to work. I have now got it working by forcing the bash shell using:

shell_exec("bash -c \"bash command <(another bash command)\"")
-1
smithnigelw at gmail dot com
6 months ago
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'.
Ashraf Kaabi
12 years ago
I've write a Full Class for Run in Background, Kill PID , check if is Running

<?php
/**
* @author     Ashraf M Kaabi
*/
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;
}
};
?>
rigsbr at yahoo dot com dot br
12 years ago
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).
concept at conceptonline dot hu
13 years ago
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.
James McCormack
14 years ago
I had a perl program which ran fine from command line but not using shell_exec(), exec() or system() - nothing was being returned. I was using the full path and permissions were set correctly.

It turned out the perl program was using more memory than my PHP.INI file was set to allow. Increasing "memory_limit" solved the problem.
-1
php [AT] jsomers [DOT] be
13 years ago
<?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.
-2
Paul Cook
12 years ago
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.
-1
martin at intelli-gens dot com
8 years ago
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')

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
-1
phillipberry at NOSPAM dot blisswebhosting dot com
13 years ago
I found something odd.

If you run exec then straight after shell_exec the shell_exec will simply not run and will return NULL.

To get it to work i put a sleep(5) after the exec and now shell_exec works fine.
-1
ruan at nospam dot tillcor dot com
12 years ago
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.

Hope this helps somebody else out there :)

Ruan Fourie
-1
nowayoutlive.de
8 years ago
Today I needed a piece of code, which makes use of the shell_exec function. For those who want to scan 2 letter domains too, here is a nice linux and php5 way, using a character generator class.

<?php
define
("__USED_CHARS__", "abcdefghijklmnopqrstuvwxyz0123456789");
define("__CASE_SENSITIVE__", true); // Use string above or use uppercase / lowercase variant

$bf = new chargen(2); // new chargen object, length 2$bf->generate("whois"); // generate chars and call whois function

function whois($str) {$domain = $str.".com";$retval = shell_exec("whois $domain"); if ( eregi("no match",$retval))
echo
$domain." ist available\n"; else echo$domain." is unavailable\n";
}

class
chargen
{
private
$chars = NULL; private$maxlength = NULL;

protected
$buffer = NULL; function generate($mycallback = false)
{
foreach (
$this->buffer as$char)
{
foreach (
$this->chars as$nextchar)
{

$retval =$char.$nextchar;$this->buffer[$retval] =$retval;

if (
$mycallback && function_exists($mycallback))

$mycallback($retval);
else
echo
$retval."\n"; } } if ( strlen($retval) == $this->maxlength) return;$this->generate($mycallback); } function __construct($maxlength = 8)
{

$chars = array();$this->buffer = array();

array_push($this->buffer, ""); for ($i = 0; $i < strlen(__USED_CHARS__);$i++)
{

$index = substr(__USED_CHARS__,$i, 1);

if (
__CASE_SENSITIVE__)
{

$this->chars[$index] = $index; } else {$this->chars[strtolower($index)] = strtolower($index);

$this->chars[strtoupper($index)] = strtoupper($index); } }$this->maxlength = $maxlength; } } ?> -1 d-skyman at gmx dot de 11 years ago 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>"; ?> -2 fabjoa dot mwoz at gmail dot com 8 years ago 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! if(trim(shell_exec('whoami'))!='www-data') -1 dae3 9 years ago Beware of the following inconsistency: shell_exec() and the backtick operator will not return a string if the command's output is empty -- they'll return NULL instead. This will make strict comparisons to '' return false. -1 Woody/mC 11 years ago 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. -1 leaetherstrip at inbox dot ru 14 years ago Note on XP users: XP-Home edition does not allow to set rights directly on files and folders. You should use 'cacls' command-line utility to do this. For example: cacls c:\windows\system32\cmd.exe /E /G IUSR_ADMIN2003:F gives IIS user full access to cmd.exe (potential security hole!), so PHP can fork and execute external programs. -1 Ben 15 years ago 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:$remaddr = getenv("REMOTE_ADDR");
putenv("REMOTE_ADDR=$remaddr"); shell_exec("/path/to/subprocess"); -2 guenter at grodotzki dot ph 10 years ago If the return is empty, then command could not be executed or executed command returned an error. -3 flame 15 years ago add '2>&1' to the end of your shell command to have STDERR returned as well as STDOUT.$shell_return = shell_exec($shell_command." 2>&1"); -6 ptitjib at hotmail dot fr 6 years ago 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. -2 php at chris-decker dot com 16 years ago I have found it easiest to use the following code to execute a shell command and return all of it's output (not just the last line) to the user as if he/she were sitting at the terminal:$output = shell_exec("$command"); echo(nl2br($output));
-3
RayJ
11 years ago
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.

<?php
$runCommand = 'php -q FULLPATH/FILE.php'; if(isset($_SERVER['PWD'])//*nix (aka NOT windows)

{

$nullResult = $runCommand > /dev/null &;
}
else
//windowz

{

$WshShell = new COM("WScript.Shell");$oExec = $WshShell->Run($runCommand, 7, false);
}
?>

Also, to get the correct "basepath" from the script that runs in the background. try:

<?php
ignore_user_abort
(true);

set_time_limit(0);

if(isset(
$_SERVER['PWD'])) {$basepath = $_SERVER['PWD']; } else {$basepath = ereg_replace('[^/]*$', '',$_SERVER['PHP_SELF']); }

$extendedpath = '/path1/path2/';$basepath = preg_replace("|(?:{$extendedpath})$|i",'',$basepath); echo 'Start In: '.$basepath;
?>

Enjoy!

Later, RayJ
-3
arturm at union dot com dot pl
12 years ago
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:
flush();
$result = shell_exec('C:\util\myprog.exe'); -4 Kishan 12 years ago If you are on windows and has Cygwin, You can execute all your Cygwin binaries using shell_exec() as follows: <?$result = shell_exec("C:\cygwin\bin\bash.exe --login  -c '/cygdrive/c/cygwin/bin/convert.exe --version'");
print($result); ?> 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"
-2
xxxpaul1104xxx at gmail dot com
4 years ago
//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"
-1
bruce at accumatics dot com
15 years ago
If you're not getting any output from echo shellexec( "count.pl" ) [for instance], at least try "./count.pl" before bothering with the full path.
-3
vsuarez at vorealis dot com
14 years ago
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.
-3
eremi at eremi dot net
15 years ago
To output the command has it should be, you can do the str_replace trick above, or you can put the output in a <pre> tag.

Example:
<?php
$output = shell_exec("[command]"); echo "<pre>$output</pre>";
?>
-4
notmespammers-iain at iaindooley dot com
12 years ago
beware!

shell_exec('cd /path/to/dir');
shell_exec('ls -l');

will not give a listing of /path/to/dir!! use chdir() if you need to change directories, or group your commands with && (not always convenient/possible)

cheers

iain
-3
zd
9 years ago
It's probably worth noting that shell_exec() return value seems binary safe, while the output array from exec() is not.

In either case, a more controlled way to launch and interact with a process is proc_open() which allows you to have streams and is also binary safe.
-3
sa577 at gre dot ac dot uk
10 years ago
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.
-3
Kenneth
13 years ago
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.

Hope this helps
-6
kees dot schepers at infolook dot nl
12 years ago
If you are using a Windows server with IIS, and you try to execture a batch file with shell_exec() function, or his related functions you should do it like this:

<?
shell_exec("C:\\path\\to\\cmd.exe /c C:\\batchfile.cmd");
?>

Note the parameter /c which says "Carries out the ommand specified by string and then terminates"

If you don't add the parameter /c the batch file will not be executed, only the cmd.exe file will.

As, also mentiod in these commants, put your cmd.exe file in your php folder, and your windows folder for security reasons.
-22
ilya at linemedia dot ru
7 years ago
sudo can be executed without storing pass in a file

system('echo "PASS" | sudo -u root -S COMMAND');
-2
spagmoid at yahoo dot NOSPAMcom
14 years ago
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.
-2
dan at mathjunkies.com
15 years ago
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.
-6
squeegee
12 years ago
Each time you call shell_exec, it operates in a completely new shell. So if you need to do different multiple things in it based on whatever criteria, assemble your command ahead of time:

<?php
shell_exec
("cd $path_to_dir"); shell_exec("ls -l"); ?> which, as you noted, won't work, do <?php$cmd
= "cd $path_to_dir; "; if($a == true)$cmd .= "ls -l"; else$cmd .= "du -h";
$result = shell_exec($cmd);
?>
-4
16 years ago
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.
-9
redtuugii at yahoo dot com
10 years ago
if you want get exit status

<?php
$command = 'ls -lpas'; // Execute the shell command$shellOutput = shell_exec($command.' > /dev/null; echo$?');

//return execute status;
echo trim($shellOutput); ?> -5 ludvig dot ericson at gmail dot com 13 years ago (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 by ldd 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. What I did was just to run these few commands: su mkdir /jailpath && mkdir /jailpath/lib cp /lib/*.so* /jailpath/lib/ mkdir /jailpath/usr && mkdir /jailpath/usr/bin && mkdir /jailpath/usr/lib cp /usr/lib/*.so* /jailpath/usr/lib cp which php` /jailpath/usr/bin chmod -R 0755 /jailpath && chown -R root:root /jailpath && chmod 0000 /jailpath Do note that this copies _all_ of your shared objects. There is one or two more libraries you have top copy, but chroot will tell you about which one it is. Hope this helped somehow. -6 ben at thelocust dot org 10 years ago 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. -6 dk at brightbyte dot de 13 years ago 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: <?php 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: <?php$result
= runExternal("ls -l some-file.txt",$code); print "<pre>"; print$result;
print
"</pre>\n";

print
"<b>code: $code</b>\n"; ?> enjoy :-) -10 moneyboi at fuckwindows dot com 15 years ago shell_exec("yourscript.sh") is great for opening shell scripts. -5 ericphp at shepard dot com 14 years ago I had major problems getting sell_exec() to work from PHP. It was working fine via the Telnet command line. Turns out (for me anyway) it was a pathing problem. I'm set up on a VPS FreeBSD server the does not (technically) have root access. PHP needs to reference the FULL PATH to the app it's calling. But it gets more tricky than that. There may be more than one full path on a server. For instance, on mine there is: >find ~/ -name mysqldump (VPS non-root search method) /usr/local/bin/mysqldump /usr/home/myusername/usr/local/bin/mysqldump /usr/home/myusername/usr/local/mysql-3.23.41/bin/mysqldump /usr/home/myusername/usr/local/mysql-3.23.43/bin/mysqldump Turns out (after 5 hours of hair pulling fun) that /usr/home/myusername/usr/local/mysql-3.23.43/bin/mysqldump was the winner. The same applies to using cURL and PHP via Cron. /usr/home/myusername/usr/local/curl-7.10.5/bin/curl works for me there. And tar wouldn't work until I dug up PHPTAR /usr/home/myusername/usr/local/bin/phptar. Never new that existed ... Good luck. -5 ron dot petty at unigeek dot com 15 years ago Here is an example on how to install software using php shell_exec("cd /usr/local/src/; gunzip program.tar.gz; tar xvf program.tar; cd program; ./configure; make; make install); 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. -6 dj-bj at gmx dot net 14 years ago shell_exec passes the result to a variable only if the result of the command is true. When the result is false the generated page contains the error string in clear text at the position the result was fetched (which can differ from reload to reload). If you would like to recieve also the error messages append 2>&1 to the end of the command you are executing. However, the result is also passed to the page directly. To avoid page destruction you should not fetch the result in your script. By appending >nul to the shell command you can hide any output. Hope this helps. -11 Anonymous 10 years ago 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. -5 ryon -at- ryon labaw -dot- com 15 years ago Note: You cant used shell_exec() when safemode = on (its disabled), instead use exec() and copy the needed program into the /nonexec directory (by default, set in php.ini). -5 dj-bj at gmx dot net 15 years ago 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. -9 doo_mangle_fus at by_mangle_u dizzot net 12 years ago 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: <?php$passwd
= 'censored';
$filename = 'archive.zip';$options = '-o'//Overwrite existing files by default; this is mostly to suppress confirmations
$destDir = ''; if (isset ($_POST['password']))  {
if (
$_POST['password'] ==$passwd)  {
if (isset (
$_POST['filename'])) {$filename = escapeshellarg ($_POST['filename']); } if (isset ($_POST['updateExisting']))  { $options .= "u"; } //use with care, since a timezone mismatch may occur; see man unzip if (isset ($_POST['destDir']))  { $destDir = ' -d '. escapeshellarg ($_POST['destDir']); }

echo
"<pre>";
echo
shell_exec ("unzip $options {$filename}{$destDir}"); echo "</pre>"; } else { outputPage ("Your password didn't check out, mon. Better try it again, eh?"); } } else { outputPage(); } function outputPage ($errorMessage = '')  {
echo <<<HTML
<style type="text/css">
td.left  { text-align: right; }
td.right { text-align: left; }

div  { color: red; border: 1px solid gray; padding: 4px; }
</style>
<body>
HTML;

if (!empty (
$errorMessage)) { echo "\n<div>$errorMessage</div>\n"; }

echo <<<HTMLL
<h1>Super Duper File Unzipper</h1>
<form name="zipform" method="post" action="unzipper.php">
<table>
<tr>
<td class="left">Filename:</td>
<td class="right"><input type="text" name="filename" size="50" maxlength="255" /></td>
</tr><tr>
<td class="left">Destination Directory:</td>
<td class="right"><input type="text" name="destdir" size="50" maxlength="1000" /></td>
</tr><tr>
<tr>
<td colspan="2"><input type="checkbox" name="updateExisting" />Update existing files</td>
</tr><tr>
<td class="right"><input type="reset" value="Reset" /></td>
<td class="left"><input type="submit" value="Unzip it!" /></td>
</tr>
</table>

</form>
</body>
</html>
HTMLL;
}
?>