Search code examples
phpajaxwindowsbatch-filecmd

Running a batch script through PHP on Windows without waiting for the script to end


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);

Solution

  • Ok, I found a workaround.

    Instead of

    exec($cmd)
    

    I used

    $filename = "help.bat";
    $file = fopen($filename,'a+');
    fwrite($file, $cmd);
    fclose($file);
    pclose(popen("start /B ". $filename, "r"));
    

    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.