McJohnson McJohnson - 1 year ago 57
Bash Question

Running shell_exec() in background AND getting its output afterwards

First of all, I would like to point out that this is NOT a duplicate to this or this and other related questions. I am asking how to get the output as well and my question is mostly related to that.

I need to run a bash script from PHP and get its output in PHP. However, doing:

echo shell_exec('script');

dies out on the 60th second due to Apache's FcgidIOTimeout. If I use the following to run it in the background, I won't be able to get the output:

shell_exec('<myscript> > /dev/null 2>/dev/null &');

I cannot:

  • Modify the bash script;

  • The code and all the functionality needs to be in a single file (unless I use a temp file);

  • If I were to write the output of the
    function to a temp file, I would also need to find a way to verify whether the
    process has finished;

  • Using a database is an overkill which I cannot afford;

My current and only idea is to create a tmp file using PHP and write the output to it, then using
top -c | grep <myscript>
(with a refresh button) and if it returns true then it is still ongoing. However, I suspect that would not be practical and efficient in most of the time.

It is important that I use a temp file and not actually creating a "permanent" file to write to.

Answer Source
  • Solution for a similar problem: A few years ago I had a similar problem. I had to upload a file to a FTP server. I wondered how to communicate to the FTP server that the file was uploaded completely, so that the FTP server can perform some tasks on it. My solution was to rename the file to something like *.completed after it was uploaded completely. Then the process on the FTP server could look for *.completed files only.

  • Solution adjusted to your problem: I'd suggest you to rename your temp file after it was generated by your bash script. This way you can independently find out if the script was executed successfully. shell_exec() could look like this:

    shell_exec('<myscript> > tmp-file && mv tmp-file tmp-file.completed &');

    Be aware that this only redirects the channel STDOUT into the the tmp-file. If you also want to redirect STDERR into the tmp-file, try this:

    shell_exec('<myscript> &> tmp-file && mv tmp-file tmp-file.completed &');