views:

74

answers:

3

Hi,

i'm trying to spawn a daemon-like process from php on a unix environment, keep the pid for reference and keep it completely independent from httpd processes. This is useful for controlling middleware applications from administrative backoffices. I want to keep it generalized to reuse for any command, i don't want to write a .sh for every command.

using php's exec() i'm running this command:

$command = "java /myApp/TestInfiniteLoop";
$log = "/myApp/myLog.txt";
$echos = null;
$fullCommand = "bash -c 'nohup $command < /dev/null > $log 2>&1 & echo $! & exit' & echo $!";
exec($fullCommand, $echos);
$pid = (int)$echos[0] + 2;

It returns $pid but does not spawn process (or kills it immediately...).

If i run the $fullCommand on a bash shell it works perfectly. I can close the bash and everything keeps running as expected.

If i take out the "nohup " it works (but pid is +1 and not +2), but as soon as you stop httpd the process get's killed too...

  1. What is the correct way to make it work?

  2. If possible can anyone correct it to get the pid directly? i'm assuming it is the second process from the bash (+2) call, but it is possible (though not probable, i know...) that it wouldn't be the same.

PS: i've been testing it on Mac and Linux environments.

A: 

One thing I've done in the past is have a separate process (like a python or c application) already running that watches either a text file or a database. The php process either writes to the file or database, and the other process, which is running as a separate user with separate permissions is polling that file or database. When it sees what it's looking for, it does whatever it needs to, reporting progress back to the file or database. That way you have a lot more freedom and flexibility in what the app does (it could write its pid to the file, for example, so that php knows what it is).

Bob Baddeley
That seems way to complicated and full of holes for what i want to do... I'm trying to implement it in a library for general usage :/For specific usage i'd just do it with init.d
Trouts
A: 

I would look into something like gearman api, which is designed to create long running processes (and then spawn actions from that) rather than try to spawn applications yourself and try to figure out the pid (it will have the side benifit of being a lot more cross platform as well). The +2 pid will definitely have race condition problems.

Kris Erickson
Yes, it would work, but i'm looking for a low level simple solution using only php itself and the unix environment
Trouts
+1  A: 

You almost have it. I think you may have too many pipes going on and the http process isn't disconnecting because it's waiting for output. This will work:

$command = 'java /myApp/TestInfiniteLoop';
exec('nohup '.$command.' >> /myApp/myLog.txt 2>&1 & echo $!', $pid);
$pid = (int)$pid[0];

I do this with PHP scripts all the time, you don't have to write a shell script.

Brent Baisley
OK, now i'm getting "nohup: can't detach from console: Inappropriate ioctl for device" in the log.txt - is it missing < /dev/null somewhere?
Trouts
in this case it's something to do with php specifics because this exact command seems to work fine as expected in the bash
Trouts
Inappropriate ioctl for device, probably means your java code is trying to connect to an input or output device which is not accessible. I'm curious if it runs under cron.
Brent Baisley
Might be related to using $! to get the PID. I've never had a problem, but I never spawned java processes. This might help http://stackoverflow.com/questions/1605195/inappropriate-ioctl-for-device
Brent Baisley
Well, further research: "Inappropriate ioctl" only comes up on Mac. On Linux it works fine, but still get's killed on httpd restart. httpd hangs a little on restart probably meaning it's waiting for my java app to shutdown and then it simply kills it. Any more ideas?
Trouts