i wanna to use php to run a background process in a linux server, i try this:
exec("abc &") ;
however, it's not work. the script will stop here until "abc" is finished.
what's wrong?
Please Help!
Thx!
i wanna to use php to run a background process in a linux server, i try this:
exec("abc &") ;
however, it's not work. the script will stop here until "abc" is finished.
what's wrong?
Please Help!
Thx!
See the documentation for
exec
system
passthru
escapeshellcmd
I did this a while ago... It required the use of a special C program function that I found somewhere on the internet...
#1, you MUST compile the C program first.
Here is the C program. It's really simple, if you know C ;)=
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int pid;
cout << "BGSTART: command [arguments]" << endl;
cout << "Number of arguments: " << argc;
for( int counter = 0; counter < argc; counter++ ) {
cout << " argc[" << counter << "]: " << argv[ counter ] << endl;
}
cout << "Forking off..." << endl;
pid=fork();
if (pid!=0)
{
//executing the program passed in on the command line
close(STDOUT_FILENO);
close(STDIN_FILENO);
close(STDERR_FILENO);
execvp(argv[1], &argv[1]);
// http://www.php.net/manual/ref.exec.php3
// http://home.i1.net/~naken/mikehup.c
}
return 0;
}
I'm not that great at C, and I don't remember if this is the version of the code that I compiled, but it's the only thing I have in my directory, so it's what I'm spitting out at you. I called it 'bgstart', you can call it whatever you'd like.
#2, use it in your php code like this:
<?PHP
$mp3_to_play = EscapeShellCmd( $mp3_to_play );
$command = "/usr/local/bin/bgstart /usr/bin/mpg123 $mp3_to_play &";
?>
#3, you can see it in action here:
http://24.17.173.98/~rames/audio/cdplayer/music.php
I just upgraded from php3->php4 at home, so if you click around to some of the other stuff, i'm sure you'll see some broken things, but feel free.
#4, the reason for all this...
PHP is kindof cool in that it will wait for a process to finish before executing the next line of code. It allows you to 'exec' system commands just as if they were a line of PHP code. But that's the problem you're trying to get around- you don't want to wait for that process to finish, you want to let the computer do it's whole computing thing while the user gets on with their life.
What 'bgstart' does is start up really quick, use fork to make another copy of itself (which php doesn't know about). Within that new process, it runs your processor-intensive code (and php doesn't know about it), and then it just executes a "return(0)" for the process that php does know about.
PHP sees that the process it launched (bgstart) terminated, while the other program (in my case, mpg123) continues running merrily. PHP then returns control to the next command in your php script because 'bgstart' has already terminated.
Hope this helps, and I hope that the c proggie i gave you actually does compile. :)=
--Robert
Thanks Robert!
buti have a question about #2.
is the "&" is no use in the $command?
Since "&" is use for start a bg process.
Thanks!
Guys, you don't need a special C program (and actually that is not C; it is C++). Read the documentation for exec and system as I suggested. They do exactly the same thing as the similar functions in the C library.
Sorry Steve, i have read the document seveal times, but i havn't got the answer.
Since the document only talk about how to execute an external program, but nothing about how to create a background process.
My problem is i can execute an external program, but i don't want to wait it until it's finish.
can u tell me more detail?
thx!
Summary:
exec() directly invokes a program
system() passes a command to a shell process
The big difference is that the shell process understands metacharacters such as < and > and | and &.
The operating system does not process those metacharacters; when you type something at a Unix command line that contains them, the shell is responsible for processing them.
So, you were on the right track at the start but you weren't using the right function. You weren't passing the metacharacters to anything that could possibly understand them.
If you need to start a process in the background, use system() and pass it an appropriate command line for the shell (most likely bash on a Linux system) to process.
Pay particular attention to what the manual says about redirecting output. You probably want to do something like this
system("myprog myargs >>/dev/null 2>>/dev/null & ");
Note that there are some security dangers associated with using system(). Never take user input from a form and pass it directly to system() without scrubbing it first through escapeshellcommand().
Yes, i get it!
Thx a lot steve!
Oh!!
i have tried it, but it still hold up in the system(} line until the process finish!
the differnce is system() will display process output and exec() will not!
What's the problem?
p.s. i'm using Redhat6.2 and PHP3.0.16
Sounds like you are not redirecting output to /dev/null.
<?
system("ls -l .. >>/dev/null &");
echo "done";
?>
oh.. ic!
it works well!
thx!
One more question,although i don't think it's work, can i do something like that in NT/Windows?
The problem that you seem to be discussing seems to be identical to mine. Your solution seems to be deviced to work for Linux and Unix based systems. I am doing it the hard way, I have win98, Apache and PHP4. Do you think that the sintax is still the same, or...
Please advice.
I don't think it will work on win9x, as there is no support in the command.com shell for multitasking.
The W98-problem
My problem is that I have to set of computation in an external program that could take minutes and as long as days. Therefore, I need to get arround this problem. Is there any known way around this (that is to say, running the external program and leave it working in the background, without waiting for result), else than setting up linux on my machine.
Many great thanks.
HJ
your message:
Sounds like you are not redirecting output to /dev/null.
<?
system("ls -l .. >>/dev/null &");
echo "done";
?>
If I want to do similar to exec("cmd",$array,$err_code)
and use redirection to /dev/null inside the quotes(which may be the only way no to let the process hang), I won't be able to capture any error message, which I need to put somewhere. Any suggestion?
I tried the background execution, using both two methods (the C program and the system() call). Both two methods were Ok.
The background execution starts, the page appears, and it all seems to be ok. Then I click in another link and the Apache server hangs! Why? (BTW: when I kill the background script, the apache unlocks and goes on)
:-? Why? The execution launched ok because the PHP continued. Why the NEXT request locks?
Hi Daniel
I got exactly the same problem, if i execute my program in the background, it seems to be fine, but the Apache-Server until i kill the background-process.
Did you find the solution ?
the problem with the C program posted is that it is written for unix. after spending a lot of time, trying to make something similar, i finally found an explanation on :
http://www.naken.cc/projects.php
the thing is that you need to close the stdin/stdout/stderr before spawning the new process. to do this you can compile the following program (in VC++6.0) or just get the executable from my site :
http://swaxi.fnuque.dk/download/serverbins.zip (witch contains commandline tools for rebooting+shutdown too in case you should need that)
#include <process.h>
#include <string.h>
#include <stdio.h>
#include <io.h>
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
char * cl = GetCommandLine();
char *token;
void * argv[1024];
int argc = 0;
token = strtok( cl, " " );
while( token != NULL )
{
/* While there are tokens in "string" */
char * tok = new char[1024];
strcpy(tok, token);
argv[argc++] = tok;
/* Get next token: */
token = strtok( NULL, " " );
}
fclose(stdin);
fclose(stdout);
fclose(stderr);
_spawnv( _P_DETACH, (char*)argv[1], (const char *const *)argv );
return 0;
}