Edit: See my answer to this post for the solution to this particular problem; I also removed parts of the question which were no longer relevant to the solution.
I’m new to PHP and development in general and I’m asking, because I haven’t found a working solution for my problem yet.
As part of a project I am trying to run a batch script. The batch script creates some analysis files and crucially compiles and starts 2 executables I need to keep running for later.
To start the script, I compose a call $cmd where I set 2 environment variables and the working directory and add some necessary parameters that the script needs in order to start.
I then run
exec($cmd);
This call produces all files in the working directory, and starts the processes, however the batch script now waits for the executable processes to finish, as it cleans up some temporary files after the programs are finished. At this point the PHP program stops executing and waits for the batch script to finish, which it doesn’t do.
Over the course of the last 2 days I have tried multiple solutions proposed here
or
exec($cmd.' > NUL 2>&1 &')
and
pclose(popen("start /B " . $cmd . " 1> ".$scrptDir." 2>&1 &", "r"));
where $scrptDir
is the working directory I described earlier.
I have not found a working solution, at best the script doesn’t start at all and at worst it produces a syntax error when making an AJAX call, which admittedly I have not yet understood why exactly it does that, as AJAX was implemented by a predecessor and left pretty undocumented.
Edit: The syntax errors were caused by myself, because I forgot the semicolon.
This is the PHP code:
public function runScript() {
//-- compose the command line to start script
$cmd = $this->getCall();
//-- execute the script
exec($cmd);
}
}
Updates:
Starting the script via
pclose(popen("start /B " . $cmd . " 1> NUL 2>&1 &", "r"));
or
popen("start /B " . $cmd . " 1> NUL 2>&1 &", "r");
or
exec('nohup ' . $cmd . ' 2>&1 &');
has the same outcome: the script runs, but the executables close and the script performs the cleanup.
Using
exec($cmd.' > NUL 2>&1 &');
does not have different behaviour from
exec($cmd);
2
Answers
Ok, I found a workaround.
Instead of
I used
I wrote the composed command $cmd into a batch file and then executed that batch file instead. I think the reason why it is working now is that my composed call was a bit too complex for me, so I tried to make it simpler.
This is one way to do it. Please be advised that this is not the best way to go about it, especially if you need to do something with the results of an AJAX call.
jQuery
Let’s say that you initiate the AJAX request like this:
The key part here is the
timeout
. This will abort the pending AJAX, meaning that the JS will not wait for the response, but the server-side script called with it will still execute.Vanilla Javascript
If you’re not using jQuery, you could do the same thing in vanilla Javascript, like this.
If you’re unsure whether the AJAX request is reaching the backend, and there are no console errors or network errors, you can do the following.
First, create a script called
test.php
(or give it another name, if you already have a script called like that). Then, inside that script, place the following.What this will do is:
sleep(15)
does)fclose(...)
after fwrite(…). This is generally not good practice, because something might break the script execution, and the file would remain locked, but it’s alright in this case, because it’s for testing purposessleep(5)
), and then write the current date and time to it.PHP_EOL
is the newline characterThe next step is to replace
myscript.php
call inside your AJAX, so that it callstest.php
. The rest of your AJAX setup can remain the same.Then, execute AJAX as if you would normally. Wait for about 20 seconds, and check if a file called
zztest.txt
has been created, and if it has, what its contents are.If it hasn’t, then the problem is in the front-end (the AJAX call).