shell_exec
(PHP 4, PHP 5, PHP 7, PHP 8)
shell_exec — シェルによりコマンドを実行し、文字列として出力全体を返す
説明
この関数は バッククォート演算子 と等価です。
注意:
Windows では、パイプがテキストモードでオープンされるため、 この出力を使ったバイナリの出力が失敗する可能性があります。 このような場合は、popen() の利用を検討してください。
パラメータ
command
-
実行するコマンド
戻り値
実行されたコマンドからの出力を文字列で返します。
パイプがオープンできなかった場合は false
を返します。
エラーが発生したり、コマンドが何も出力しなかった場合は null
を返します。
注意:
この関数は、エラーが発生した場合だけでなくプログラムが何も出力しなかった場合にも
null
を返します。 そのため、実行に失敗したかどうかをこの関数では判断できません。 プログラムの終了コードを調べる必要があるときには exec() を使いましょう。
エラー / 例外
パイプがオープンできなかった場合は
E_WARNING
レベルの警告が発生します。
例
例1 shell_exec() の例
<?php
$output = shell_exec('ls -lart');
echo "<pre>$output</pre>";
?>
+add a note
User Contributed Notes 35 notes
trev at dedicate.co.uk ¶
13 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.
alexandre dot schmidt at gmail dot com ¶
9 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.
mamedul.github.io ¶
1 year ago
Cross function solutions for execute command using PHP-
function php_exec( $cmd ){
if( function_exists('exec') ){
$output = array();
$return_var = 0;
exec($cmd, $output, $return_var);
return implode( " ", array_values($output) );
}else if( function_exists('shell_exec') ){
return shell_exec($cmd);
}else if( function_exists('system') ){
$return_var = 0;
return system($cmd, $return_var);
}else if( function_exists('passthru') ){
$return_var = 0;
ob_start();
passthru($cmd, $return_var);
$output = ob_get_contents();
ob_end_clean(); //Use this instead of ob_flush()
return $output;
}else if( function_exists('proc_open') ){
$proc=proc_open($cmd,
array(
array("pipe","r"),
array("pipe","w"),
array("pipe","w")
),
$pipes);
return stream_get_contents($pipes[1]);
}else{
return "@PHP_COMMAND_NOT_SUPPORT";
}
}
shell master ¶
1 year ago
You can use a one liner to print the output of a shell script like so:
<?= shell_exec("/proof.sh"); ?>
Rgemini ¶
15 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.
smcbride at msn dot com ¶
4 years ago
proc_open is probably a better solution for most use cases as of PHP 7.4. There is better control and platform independence. If you still want to use shell_exec(), I like to wrap it with a function that allows better control.
Something like below solves some problems with background process issues on apache/php. It also
public function sh_exec(string $cmd, string $outputfile = "", string $pidfile = "", bool $mergestderror = true, bool $bg = false) {
$fullcmd = $cmd;
if(strlen($outputfile) > 0) $fullcmd .= " >> " . $outputfile;
if($mergestderror) $fullcmd .= " 2>&1";
if($bg) {
$fullcmd = "nohup " . $fullcmd . " &";
if(strlen($pidfile)) $fullcmd .= " echo $! > " . $pidfile;
} else {
if(strlen($pidfile) > 0) $fullcmd .= "; echo $$ > " . $pidfile;
}
shell_exec($fullcmd);
}
eric dot peyremorte at iut-valence dot fr ¶
17 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);
Just adapt it to your language locale.
Which shell? ¶
2 years ago
Does anything, anywhere mention WHICH SHELL shell_exec() runs?...on my system, it's running sh, instead of bash, which causes <() Process Substitution to fail with no error msg.
Shouldn't the docs mention which shell this function (& backticks ``) runs?
kamermans at teratechnologies dot net ¶
17 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.
RoBorg ¶
17 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()
pedroxam at gmail dot com ¶
5 years ago
Here is my gist to all:
function execCommand($command, $log) {
if (substr(php_uname(), 0, 7) == "Windows")
{
//windows
pclose(popen("start /B " . $command . " 1> $log 2>&1", "r"));
}
else
{
//linux
shell_exec( $command . " 1> $log 2>&1" );
}
return false;
}
joelhy ¶
15 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');
?>
jack dot harris-7ot2j4ip at yopmail dot Com ¶
10 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.
codeslinger at compsalot dot com ¶
14 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 ¶
22 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
saivert at saivert dot com ¶
16 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.
Anonymous ¶
19 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!
rustleb at hotmail dot com ¶
18 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.
mcbeth at broggs dot org ¶
21 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