文字

程序执行 函数

注释

Warning

以加锁方式打开的文件(特别是在打开会话时), 必须在执行后台程序之前关闭。

参见

这些函数和 执行运算符 是紧密关联的。 因此,当运行在 安全模式 是,你必须考虑 safe_mode_exec_dir 指示。

Table of Contents

  • escapeshellarg — 把字符串转码为可以在 shell 命令里使用的参数
  • escapeshellcmd — shell 元字符转义
  • exec — 执行一个外部程序
  • passthru — 执行外部程序并且显示原始输出
  • proc_close — 关闭由 proc_open 打开的进程并且返回进程退出码
  • proc_get_status — 获取由 proc_open 函数打开的进程的信息
  • proc_nice — 修改当前进程的优先级
  • proc_open — 执行一个命令,并且打开用来输入/输出的文件指针。
  • proc_terminate — 杀除由 proc_open 打开的进程
  • shell_exec — 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
  • system — 执行外部程序,并且显示输出

用户评论:

[#1] benkitzelman at yahoo dot co dot uk [2010-08-20 08:02:37]

Within Linux, when calling the php interpreter directly from popen, or other program execution function to execute a script, it appears as though the script perpetually fails and re-executes. 

i.e. <?php popen("php myscript.php&", "w"); // fail ?>

As each re-execution causes the executing script to load under a new PID, it is incredibly difficult to identify and kill the process manually. 

[One solution is] to ensure the executing script has a valid shebang, and execute permissions. This allows you to execute the script directly

i.e. <?php popen("./myscript.php", "w"); // ok ?>

[#2] Anonymous [2008-07-09 10:34:37]

I found this comment on this page:

[begin of quote]
Trying to us the following code failed badly with various results: like "unable to fork", "access denied", "empty results", depending on what settings I used, ... even though the same code worked from command line on the server itself.

$retstr = exec('nslookup -type=mx myhost.com', $retarr);

Instead of nslookup I believe this would apply to most programs from the \system32\ directory.

I had to learn that the following finally worked:
$retstr = exec('c:\php\safedir\nslookup -type=mx myhost.com', $retarr);

... but only under the listed preconditions:
1: nslookup.exe is placed (copied) in the directory \php\safedir\
2: the directory \php\safedir\ is included in the system PATH environement variable
3: the file cmd.exe is placed in \php\ as listed by other notes above
4: the directory "c:\php\safedir\" is set in the php.ini setting 
safe_mode_exec_dir = "c:\php\safedir\"
.. maybe set in php-activescript.ini as well, depending on your system setup.
5: nslookup is referenced by the full path as otherwise the file from \windows\system32\ will be called. This happend to me with empty result due to missing rights!

Hope this helps somebody saving some time and headaches.
[end of quote]

This is just to complicated. Only two things are needed:
1. Specific permissions for the IUSR account for read & execute to the cmd.exe in C:\Windows\System32 directory
2. Specific permissions for the IUSR account for read & execute to the command that's needed (example: nslookup.exe in C:\Widnows\System23 directory)

With just this two conditions the exec works fine

(This is for an IIS server running on a windows platform)

[#3] mosesdinakaran at yahoo dot co dot in [2008-03-17 06:49:58]

Hi 

     I had  problem with executing   exec(),shell_exec() (PHP is not running on Safe Mode).

     After spending some time I was able to find out that the Problem is  with SELinux enabled in my system. 

      You can make sure about this by seeing the log  /var/log/messages 
     So I disabled SELinux and now everything works.

     A Temporary  Disable to selinux #> setenforce 0;

     Since I felt this is not a good Idea I still went through some sites and find a solution which I felt good.

     Fedora's SELinux policy has some booleans - let's see what it has for our apache:
# /usr/sbin/getsebool -a | grep httpd
allow_httpd_anon_write -- off
allow_httpd_mod_auth_pam -- off
allow_httpd_sys_script_anon_write -- off
httpd_builtin_scripting -- on
httpd_can_network_connect -- off
httpd_can_network_connect_db -- off
httpd_can_network_relay -- off
httpd_disable_trans -- off
httpd_enable_cgi -- on
httpd_enable_ftp_server -- off
httpd_enable_homedirs -- on
httpd_rotatelogs_disable_trans -- off
httpd_ssi_exec --off
httpd_suexec_disable_trans -- off
httpd_tty_comm -- off
httpd_unified -- on
  
   From the above we can make sure that exec() is not working  because of this httpd_ssi_exec -- off   setting
  So I turned it On.
   
#> setsebool -P httpd_ssi_exec 1;
  
    Now I was able to see the output of shell_exec('ls -al')

Moses

[#4] luko post cz [2008-01-29 18:15:13]

to lancelot:

it's simple exec($my_cmd) on windows executes 'cmd /c $my_cmd'
if there are any spaces in $my_cmd you have to put it in doublequotes:
cmd /c "$app $target" will work

further if there are any spaces in $app and $target they also have to be in doublequotes:
cmd /c ""$app" "$target"" 

therefore enclose your $cmd in two more doublequotes and dont forget to escape slashes \\

$cmd = "\"\"C:\\my path with spaces\\targetapp.exe\" \"C:\\mypathnospaces\\targetfile.xxx\"\""; 

and exec($cmd) will work :)
no chdir anymore...

[#5] lancelot--du-lac at hotmail dot fr [2008-01-24 23:00:46]

The note is about usage of exec() under windows...

In replay to k dot mitz dot NO_SPAM at att dot NO_SPAM dot net: why not enclose your $cmd in simple quotes instead?

Here is where i'm at right now (also TRYING to use exec() and passthru() on windows XP sp2):

you can do this:

$cmd = '"C:\my path with spaces\targetapp.exe" C:\mypathnospaces\targetfile.xxx';
exec($cmd);

The above works.
________

Or, you can put your script into your directory C:\my path with spaces\, and work with php directly from there:

$cmd = 'targetapp.exe "C:\my other path with spaces\targetfile.xxx"';
exec($cmd);

The above also works, provided of course your script has the correct working directory.
________

But... In your cmd.exe, you can issue:

"C:\my path with spaces\targetapp.exe" "C:\my other path with spaces\targetfile.xxx"

Although the above works perfectly in the cmd, the following php script does NOT work on my system:

$cmd = '"C:\my path with spaces\targetapp.exe" "C:\my other path with spaces\targetfile.xxx"';
exec($cmd,&$content);

Not that it sends an error, it just does nothing, and you get nothing written into your $content array... Not that I do understand why.
________

As far as my few tryings go, the root of the problem lies in the fact that the command to execute has two passages enclosed inside double quotes. Another command which I've had working in the cmd but NOT with php is:

'"C:\my path with spaces\Apache2\bin\Apache.exe" -w -n "Apache2" -k restart'

Maybe someone has a solution; I don't (other than using chdir).

[#6] jakster at gmx dot net [2008-01-05 04:56:27]

To fork a process I use the following code

<?php

fclose
(STDOUT);   //Close all output or it WON'T work
fclose(STDIN);
fclose(STDERR);

if(
pcntl_fork()) {
    exit;            
//Return to the caller
}

//Code to run in the background

pcntl_exec("/usr/bin/php",Array($_SERVER['argv'][1]));

?>


I call this script from my website with
<?php 
function fork($script){        //run a forked php script relative to the document root. NO OUTPUT IS DISPLAYED!
    
global $config;
    
$cmd "/usr/bin/php \"" dirname($_SERVER['SCRIPT_FILENAME']) . "/includes/forked/forkHelper.php\" \"" $script "\"";
    
exec($cmd);
}
?>

[#7] Odie [2007-12-14 12:22:13]

When I switched our server over from running cgi mode to FastCGI I found that my exec function was no longer working in one area. I found that even when IUSR_X had read access to the appropriate areas, it could not execute the file.

Permissions on files don't seem to matter with FastCGI. You have to move any executables and files that they access outside of wwwroot. My problem was that I was running an executable that was reading a file in my web directory.

[#8] Max_R [2007-09-26 07:21:20]

Just a small notice, when running PHP under MS Windows 
some external command-line utilities (like 'ffmpeg.exe') output all info to stderr instead of stdout. In my case it caused apache error.log overfilling with lots of unsolicited records. 
It has just taken some time for me to make the utility silent:
Simply add
">NUL 2>&1" 
to the very end of your command line. It makes cmd.exe to redirect stderr to stdout and then, in one's turn, redirect stdout to NULL.

Hope this tip will save some time when dealing with such utilities.

[#9] steve dot robinson at frogneck dot com [2007-05-21 07:46:39]

If you are trying to use exec to run a cgi and output the contents via a php file, headers need to be seperated from the content and output seperately.

Also, at least in the case of the cgi I was attempting to execute, line feeds were missing, and some javascript didn't work as a result, so you may have to add line feeds back into the resulting output.  Here is the code I used to output my cgi properly...

<?PHP
putenv
('REQUEST_METHOD=GET');

// to get your parameters passed into the cgi..
putenv('QUERY_STRING=' $_SERVER['QUERY_STRING']);

//you will know you are past the header when you
//hit a blank line ('')
$inheader=true;
foreach(
$output as $val){
        if(
$val=='')
                
$inheader=false;  
        if(
$inheader)
                
header($val);
        else
                echo(
$val "\n"); // output contents
}
?>

[#10] php at fendy dot org [2007-05-02 17:51:25]

Scheduling WinXP tasks with schtasks.exe and using PHP to execute the command, may sometime fail to work.

This is because, Apache does not have the privilege to access some of the System Files when placing the scheduling. The way I'd do: is by creating a normal user account and assign Apache service to logon as that account.

Open the 'services.msc' in the 'Run' window, look for Apache in the listing, right click and get to 'Properties'. Click at the second tab 'Log On' and fill in the 'This account' fields.

Of course, Apache needs to be installed as Service during its first setup.

Hope this helps anyone.

Fendy Ahmad

[#11] pawel_do_not at spam_me_lenart dot pl [2007-04-24 04:51:31]

You must remember that if you're running your own compiled C programs and you don't get any output you probably do it like this:

printf("some text");

shell_exec and similiar functions won't display it, you must do your output as follows:

fprintf(stdout, "some text");

and then shell_exec and so will correctly read stdout (spent an hour wondering why my program isn't working when connected with PHP :)

[#12] [2007-01-29 08:16:10]

it seams to me the best way would be to copy cmd.exe to a secure directory somewhere under your web directory, add it to the windows path and then call it from there using system commands. It seams as though that would get arround any security holes

[#13] Rafael Palacios [2007-01-29 06:52:59]

Here is a way to collect all the output of a command (standard output and standard error):

$command="your command goes here";
$output=shell_exec($command." 2>&1");  //system call
print "<pre>$output</pre>\n";          //show output

[#14] Matt-kun [2006-12-08 10:50:52]

Just a simple note to help people get rid of some headaches.

when using:
<?php
       $filepath 
"the path of the file";
       
exec("program -command $filepath ");
       
fopen($filepath,rw);
?>


Make sure you use  "\ " ( \ space) for the Linux\unix path and just " " space for fopen. These are both very basic things that you wouldn't normally think to cause a problem, but when you try to pass slashes to fopen it either breaks or even better works incorrectly =D. And vise versa for any programs that use "\ " for spaces in file paths/names.

I ran into this problem when using  <?php exec(" cp $path "); ?>  and  <?php fopen("$path"); ?> . To fix it I used str_replace(" ","\ ",$path); and str_replace("\ ", " ",$path); 

*Note this is alot of sudo code, and there are faster more effecient ways of doing the same operations, but I thought this might help those who were going crazy over filepaths =D.

[#15] PHP at jyoppDot-com [2006-10-04 10:38:18]

Here's a function to launch a low-priority background process very simply, returning control to the foreground.  I found that a lot of the other approaches shown here allow the script to continue running, and the page is served up to the user, but the PHP thread that launched the process cannot be re-used until the process has completed.  Stdout and stderr need to be redirected to /dev/null to prevent this.

This is for BSD
  kill(getppid(), 15);
  argv++;
  
  return execvp(argv[0], argv);
}
(compile with gcc -O3 -o chain chain.c)
then in php, use
<?php
exec
('chain sh -c echo test');
?>

[#51] vi_pa at hotmail dot com [2002-04-05 04:17:42]

For those who want to execute a .php script to run in the background, from a
.php web page...

exec("php script.php parameters 2>dev/null >&- <&- >/dev/null &");

Where...
- php is the path to your php script executer (php has to be specifically complied to be to do this)
- script.php is the script
- parameters are none or more parameters
- 2>dev/null redirects the stderr to a file
- <&- switches off the stdin
- >&- switches off the stdout
- >dev/null redirects all other output to the file dev/null
- & direct script to run in background

This is the only way I managed to get it working (Linux & Apache, php 4x enviroment) . What is also great is that the process is forked so even though a user may close the browser that initiated the exec(), the process will still run to completion. And the dev/null file can be turned into a log.

What I found odd is that the script I was execing would run fine in the bg when executed from the command line, but not from the browser until I closed the stdin and stdout.

[#52] daniel dot hopp at godot dot de [2002-02-01 11:25:45]

Re: session_write_close()

To launch a background process within a session, I recommend
to use a start-stop-daemon and ship parameters via ENV.

Example:
----------------------------------------
<?php
  
// Within a session..
  
exec("/some/where/launch.sh 300");
  
// ..finished immediately.
?>


----------------------------------------
#!/bin/bash
# /some/where/launch.sh
T=$1
export T
DAEMON=/some/where/runme.pl
start-stop-daemon --start --quiet --background --exec $DAEMON

----------------------------------------
#!/usr/bin/perl
# /some/where/runme.pl
my $t = $ENV{'T'};
sleep($t);

----------------------------------------

[#53] edwin at bit dot nl [2002-01-23 03:47:39]

If you are using sessions and want to start a background process, you might have the following problem:
The first time you call your script everything goes fine, but when you call it again and the process is STILL running, your script seems to "freeze" until you kill the process you started the first time.

You'll have to call session_write_close(); to solve this problem. It has something to do with the fact that only one script/process can operate at once on a session. (others will be lockedout until the script finishes)

I don't know why it somehow seems to be influenced by background processes, but I tried everything and this is the only solution. (i had a perl script that "daemonized" it's self like the example in the perl manuals)

Took me a long time to figure out, thanks ian@virtisp.net! :-)

[#54] lk1 at reglos dot de [2001-10-25 03:05:48]

To keep a program running in the background on win98 the command
exec("COMMAND.COM /C START program args >NUL");
works fine for me.

[#55] naken at naken dot cc [2001-08-15 14:17:07]

Anyone who still wants a copy of mikehup.c,
I rewrote it:  http://www.naken.cc/mikehup.php
This program will help you run programs in the
background that are called with the php system()
function.

上一篇: 下一篇: