Re: run php in background "atomic"
| From: | Richard Lynch | Date: | Wed, 29 Nov 2000 02:48:54 +0000 |
| Subject: | Re: run php in background "atomic" | ||
| References: | 1 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-27758@lists.php.net to get a copy of this message | ||
> If a specific php-page is requested, there should start another process
> (php or perl - but php prefered), that takes about half a minute to
finish!
> How would I make this call without letting the client wait half a minute!
> And is it possible, if anotherone (client2) requests this page a second
> after client1, that the now started process2 waits for the finishing of
> process1???
You can exec() another Perl/PHP or any other command, subject to
permissions. Note that PHP runs as 'nobody' with a minimal shell and
minimal $PATH, *NOT* your login.
So be sure that what you are trying to exec() is world-executable and any
files it works with have suitable world read/write permissions. (Of course,
if you make a file world writable, you should be very, very, very careful
about security...)
You'll need PHP compiled as a stand-alone binary (aka CGI) in order to
invoke it from the command line. You may need to redo the "configure" step
from your long-ago installation, only without the --with-apxs
(or --with-apache) flag. Fortunately, what you did is logged in config.log
or somesuch, so it should be easy. You can then try it out from the command
line with a simple script to get the hang of it.
Next, step up to having PHP execute the file.
Then step up to have PHP exec() the file with an & as part of the command to
make it fork -- You may need to write a shell wrapper script that forks in
order to get the exec() to actually return. People have had mixed results
here, and I think it depends on how the forked process binds stdout and
stdin, but that's just a gut answer based on a couple test cases.
As far as atomicity goes, there are several possible solutions, none very
attractive:
1. Shared memory. The page you visit to invoke the process could check a
shared memory semaphore key to see if it's set, then set the key, then
exec() the process. That process will need a register-shutdown-function to
clear the semaphore key, thus insuring that the key is cleared even if that
exec-ed process pukes.
2. Shared memory (B). The exec-ed process could probably handle all the
shared memory stuff, and either report back (before forking) a failure to
execute or just leave the end-user blissfully unaware that their page hit
didn't actually do anything... (I'm not too sure about how to do that
reporting back and fork business...)
3. fopen('foo', 'w') is probably atomic -- So you could attempt to fopen()
a file and see what sort of error you get on that second hit, etc. You'll
need to definitely have all this happening in the exec-ed script, since file
descriptors don't get passed around between PHP scripts and get auto-closed
when one ends. I'd be suspicious of this as a good idea at all, and it's
definitely bad on a busy server.
4. flock(). Essentially the same as 3.
5. Database. If you are already using a database, you can simply set/clear
a flag in some one-row table. Probably the cleanest answer, but a bit
expensive to open up a database just to do that. Dunno which is cheaper --
fopen() or mysql_connect(). Depends on your hardware/OS/network and the
phase of the moon. Well, maybe not the phase of the moon. Test your box
and see. Be sure to compare under load conditions if you have a busy
server. Your results could be quite different.
Hope some of that helps. It's all definitely been done before (though I
never personally did the atomic part) so dig around for more threads in the
archives about it if you get stuck.