5

I'd use the following code:

$SERVER_PATH = dirname(__FILE__);
shell_exec($PHP_LOCATION.' '.$SERVER_PATH."/script.php?k1=v1&k2=v2 > /dev/null 2>/dev/null &");

Where:

  • $PHP_LOCATION should contain the path to PHP,

  • $SERVER_PATH - is current working directory (fortunately the script to run is in the same directory),

  • > /dev/null 2>/dev/null & added to make this call asynchronous (taken from Asynchronous shell exec in PHP question)

This code has two problems:

  1. As far as I remember ?k1=v1&k2=v2 will work for web-call only, so in this particular case parameters will not be passed to the script.

  2. I don't really know how to init the $PHP_LOCATION variable to be flexible and to work on the most hosts.

I conducted some research regarding both problems:

To solve 1 suggested to use -- 'parameters_string' but it is also recommended to modify the script to parse parameters string which looks a bit clumsy. Is there a better solution?

To solve 2 I found a solution to use PHP_BINARY but this is a PHP 5.4+ case (I'm using 5.3). But the original question was about to run PHP of the same version as the original script version. So for me (as I use PHP 5.3 only) is there probably a solution?

EDIT 0

Let me do some explanation why I stuck to this weird (for PHP) approach:

Those PHP scripts should be separate from each other:

  • one of those will analyze the data and

  • the second will generate PNG graphs as a final result.

Those scripts aren't intended to run simultaneously, this means that the second can run at it's own schedule it is only needed that the run should be upon its data will be ready (which done by the first script). So no data should be passed back from second script (child) to the first (parent).

EDIT 1

As seeing from most of the comments the main discussion goes to forking direction. However I'd like to make stress on the point 1 and 2 asked in the original questions. I have some reasons to solve the task in the way I pointed out and I tried to point all that reason. If some of my points looks weird, please post a comment - I will make it more clear or I will change the main question.

Thank you in advance!

12
  • 1
    why don't you use include_once('file path') ? Commented Jul 22, 2015 at 9:01
  • @AbdoAdel I need it to be asyncronous. So this is why I'd like to run a separate process. In case on include the main script will not get the control until the child process finish Commented Jul 22, 2015 at 9:04
  • 2
    Sounds like PHP isn’t the best choice for the problem you’re trying to solve then, and a threaded language is. Commented Jul 22, 2015 at 9:07
  • I agree, @MartinBean, but now I can write on PHP and JS only :( Commented Jul 22, 2015 at 9:08
  • @MartinBean given the fact one can use threads with PHP, where does that leave us at? Commented Jul 22, 2015 at 9:11

1 Answer 1

2

How to get executable

Assuming you're using Linux, you can use:

function getBinaryRunner($binary)
{
    return trim(shell_exec('which '.$binary));
}

For instance, same may be used for checking if needed stuff is installed:

function checkIfCommandExists($command)
{
    $result = shell_exec('which '.$command);
    return !empty($result);
}

Some points:

  • Yes, it will work only for Linux
  • You should be careful with user input if it is allowed to be passed to shell commands: escapeshellarg() and company
  • Indeed, normally PHP should not be used for stuff like this as if it is about asynchronous requests, better to either implement forking or run commands from external workers.

How to pass parameters

With doing shell_exec() via file system path you're accessing the file and, obviously, all "GET" parameters are becoming just part of file name, it is no longer "URI" as there is no web-server to process that. So you have two options:

  • Invoke call via accessing your web-server. So it will be like:

    //Yes, you will use wget or, better, curl to make web-request from CLI
    shell_exec('wget http://your.web-server.domain/script.php?foo=bar');
    

    Downside here: if you'll access your web-server via public DNS, it will cause network gap and all processing overheads. Benefit - obviously, you will not have to expect anything else in your script and make no distinction between CLI and non-CLI calls

  • Use $_SERVER array in your script and pass parameters as it should be with CLI:

    shell_exec('/usr/bin/php /path/to/script.php foo bar');
    
    //inside your script.php you will see:
    //$_SERVER['argv'][0] is "script.php"
    //$_SERVER['argv'][1] is "foo"
    //$_SERVER['argv'][2] is "bar"
    

    Yes, it will require modification in the script, and, probably, some logic of how to map "regular" web-requests and CLI ones. I would suggest even to think of separating CLI-related stuff to different scripts bundle so not to mess that logic.

More about "asynchronous run"

When you do php script.php & you just run it in background mode. That, however, still keeps parent-child relation for your process. That means - if parent process dies, it's childs will also be removed. To be precise, SIGHUP will be triggered and to avoid this situation you should use nohup command. It will allow to emulate "detaching" of a process and therefore making it's run reliable and independent of circumstances happening to parent process.

Sign up to request clarification or add additional context in comments.

5 Comments

I feel you're just propagating a bad design with this answer. And neither example will be asynchronous, which is apparently the reason for doing this in the first place. better to [..] run commands from external worker - this should be the direction to guide IMO as I commented on the question.
I'm not propagating anything as I do not suggest this way as a preferred one. Still OP asked the question - and depending on circumstances, he might or might not need implementation of forking his script processes. Either way, it is possible to achieve the thing that OP needs with only "pure CLI control" and therefore for some cases this might be valuable info
@AlmaDo thank you for such detailed answer! I've added EDIT 0 to originl question for some additional clarification.
The thing is, the answer to the question as asked is shell_exec('nohup php /whatever.php args &') which is only implied by the answer; by that I mean it doesn't directly answer the question anyway. I don't deny the info in the question is useful - but it'll be read in most cases as "has code - copy - paste - it doesn't work"
Well, you have the point in that, but then again, why write detailed answers with explanations :) I'm not a copy-pasta fun and thus I hope that the answer will be read carefully as I tried to provide detailed info. If solve the original problem with parallel processing from the beginning, we can reach the point when it will be - the language itself isn't so good and we need to choose go lang for instance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.