2

I have a website that lets user select test scripts, and after submitting the desired test, it will POST to insert.php and:

  1. It inserts sends a row into MySQL database in the with done=0 (insert.php).

  2. There is a listener script (testexe.php) that I want to continuously run on the webserver (maybe sleep 10 seconds) and listen to whenever there are rows with done=0, execute them and then change done=1, and move on to the next one.

I have this script running in a while loop, however, I have a question, how can this php script initially be called? Or how can I activate it to initially start? do I have to run it like php testexe.php on the server first before submitting tests? cause I know this script just listen to events, in my case the events are done=0, but how can I keep this script running all the time (system bootup)? I don't quite get this part.

The reason I want to do it this way is because there could be multiple users sending request simultaneously, so I want to make sure they process the test one by one and queue them up.

testexe.php

<?php

...
...    

//while there are still jobs that are not done..
while (1) {
    //wait for 10 seconds and query again...
    sleep(10);
    $statusResult = mysqli_query($dbConnection, $qStatus);
    //if there are undone jobs we pick them and execute them
    if (mysqli_num_rows($statusResult) > 0){
        //query the next undone test case
        $testResult = mysqli_query($dbConnection, $qNextTest);

        //fetch the returned query object and store needed parameters 
        $row = $testResult->fetch_assoc();
        $id = $row['id'];               
        $test_script = $row['test_script']; 
        $gateway = $row['gateway'];         


        if ($connection = @ssh2_connect($gateway, 22)) {
            ssh2_auth_password($connection, $user, $password);

            //execute the test case
            $stream = ssh2_exec($connection, "/my/path/to/script.sh"); 

            //fetch output stream and stderr
            stream_set_blocking($stream, true);
            $stream_out = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
            $stream_err = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
            while($line = fgets($stream_out)) {flush(); echo '<pre>' . $line . '</pre>';}               
            echo '<pre>' . "------------------------\n" . '</pre>';
            while($line = fgets($stream_err)) {flush(); echo '<pre>' . $line . '</pre>';}
            fclose($stream);    

            //update the table after the above script is done
            $qUpdateStatus = "UPDATE table SET status = 1 WHERE id = $id";
            $updateresult = mysqli_query($dbConnection, $qUpdateStatus);
        }

    }
}

?>
tiger_groove
  • 956
  • 2
  • 17
  • 46

2 Answers2

1

I can think of two options: (1) create a cron job on your webserver that calls testexe.php every ~5 minutes, or (2) have the POST execute the testexe.php script with the caveat that testexe.php checks if another instance of testexe.php is currently running.

Craig
  • 456
  • 5
  • 14
  • Thank you for your answer, I had a question I asked Paul above, perhaps you could help answer this as well. – tiger_groove Sep 19 '17 at 17:45
  • Sure - you're right about load on your server. That is, you could have several testexe.php processes running at the same time because cron starts a process every minute. The way to get around this is to have testexe.php do two things first: (1) check if a flag is set which indicates if another testexe.php process is running (2) if another process is running, exit; if not, set the flag to true and then process the records where done=0 (once finished, set the flag to false). An easy type of 'flag' is to simply create a directory. If directory exists flag is true, if not, flag is false. – Craig Sep 19 '17 at 17:55
  • Would creating a directory be much faster than querying the mysql database 'done' flag? – tiger_groove Sep 19 '17 at 18:03
  • The way that you've described this is that testexe would sequentially process each row in the db where done=0. If testexe just checks the db done flag to determine if it should execute, then you could have several testexe processes running in parallel. If that's ok, sure, checking the done flag would work... – Craig Sep 19 '17 at 18:27
1

if you use Linux cron might be something for you:

Add this line to your crontab file (access via crontab -e)

10   *   *   *   *   php testexe.php

Then remove the while loop and sleep statement.

If you need something else than 10 seconds this page may help you: http://www.crontabgenerator.com/

MEE
  • 503
  • 1
  • 11
  • 21
  • I see what you mean, quick question though, if I use a crontab and let's say I set it to run every minute (remove the while loop and sleep). If I have 2 "undone" tests in my MySQL database, while it processes the first "undone" test (let's say it takes up to 5 minutes) and after one minute it is going to process the second one right? But this will create a load on the server I want the first job to finish basically when it hit `fclose($stream)` and sets the done=1, then continue to the second job. Is that possible? Or do I just have to put more check in my code to look for that? – tiger_groove Sep 19 '17 at 17:44
  • 1
    @kkmoslehpour, Hello, maybe you could add an `in progress` flag (eg. done=0 <==> not done, done=1 <==> in progress, done=2 <==> done) and stop the script if one task has this flag set. – MEE Sep 19 '17 at 17:48
  • That's what I was thinking too, let me think about this and update my code accordingly, and perhaps get your input later. Thank you. – tiger_groove Sep 19 '17 at 17:51