How do I stop a PHP script executing more than once at a time reliably?

Hi everyone,

Im no novice to PHP coding, however I am particularly stuck on one thing; getting a PHP script that executes every 3 seconds with 1 min CRON kick start to only ever run once at a time, and not overlap.

I have tried creating a text file and the script checking if it exists before continuing then deleting it after execution. and also updating a MYSQL table in a similar manner to determine whether the script is running or not.

Please see my example below of the file check I have formulated which doesnt always seem to remove the text file after execution or create it in the right directory. I am cautious not to use MYSQL to achieve my question and would rather do it this way to minimise server load.

Any suggestions are welcome and much appreciated.

Thank you.
// Perform initial script running check
$fileN = "check.txt";
$filename = "/public_html/serverchecks/$fileN";
if (file_exists($filename)) {
$ourFileHandle = fopen($filename, 'w') or die("can't open file");
// Delete tracing check file

Open in new window

Who is Participating?
Ray PaseurConnect With a Mentor Commented:
Hi, Matt.  A file check might appear simpler, but the DB solution might offer better performance, given the ability to index and cache the data.  If you're doing this a lot, performance might matter.

You can always post code here and ask the experts to have a look at it.  If you post code in segments and ask about "best practices" you should get pretty good results.

Best, ~Ray
Ray PaseurCommented:
What does the script do?  Can you tell us why it cannot have overlap?  There may be a better way to deal with this issue, if we have more details about the larger picture.  Thanks, ~Ray
m002_parryAuthor Commented:
The script checks a gameserver every 3 seconds for certain violations ingame and also a MYSQL database of reported players who are to be watched or monitored or removed etc.

The script once running a certain portion of code under an if condition such as;
if ($player['name'] == $swearword), will then obviously take longer to execute while it performs certain functions and checks then resulting in an overlap with CRON running it again. This results in duplicate events such as warnings made etc.

The code right at the top of the script is included below which runs the script every 3 seconds with a CRON every minute from my server.

 Thanks for the speedy response Ray.

// Run script checks every 3 secs
while ($overall_time < 60) {  $overall_time += 3; sleep(3);

Open in new window

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Ray PaseurCommented:
Here is what I would try.  Create a data base table that you can use as a "lock" with the player name, a timestamp, and the "in action" flag.  When you get to the point that you are ready to do this:

if ($player['name'] == $swearword)

Check the table to see if the "in action" flag is set in the table.  If it is, skip that player.

When the actions are complete, delete the player's row from the lock table.  Periodically examine the lock table for timestamps that are more than 15 minutes old (lost actions) and remove those.

If the lock table is well indexed, you will not see any performance issues.  Does that make sense for your application?  

Best regards, ~Ray
m002_parryAuthor Commented:
Hi ray,

I think it wont quite fit into the script I have. The solution is something I wouldnt feel comfortable implementing hence why I was after a simpler way such as a file check.

As im new here, is there a way using this site someone can review my script to check for functionality issues, "bad code" and a better way of optimisation? I understand the basics of PHP, but by the same token if an expert looked at it then maybe they could suggest or give me examples of improvements?

Thanks again for your valued input
m002_parryAuthor Commented:
The questions response in my opinion has left me clueless of the approach. There is no communication in regards to the actual questions asked, instead alternatives that have been stated in the original question as not preferred were offered.

Although there should be A* for effort, if I ask myself was the information provided useful and directly relevant to my initial question, I therefore cannot award the A or B grades. Change at your will if the user has kicked up a fuss, but as the original starter and without being funny or anything, I stick by my decision having read the help section on grading. I paid good money to join this community did I not, and as great as it is, I wasnt overly satisfied by my first question or responses. Maybe im just harsh, but such as life.
Guy Hengel [angelIII / a3]Billing EngineerCommented:
   Ray_Paseur commented, and get no further response from you, until after CV Closing request.  
   not fair to him as the volunteering experts, and not correct according to the site rules neither.
   instead of grading a C, you should have posted that you did not get enough information to continue your work...
   you could also have deleted the question.

   apart from that, I think what you are looking for is known under the term "semaphore":

Ray PaseurCommented:
@a3 - I agree - semaphore may be a way to create a good solution.  It is another lock-and-handshake technology, and that is clearly what is needed here.

@m002_parry: Really sorry if my explanation left you clueless.  I took you at your word about being no novice to PHP coding, so I did not try to provide line-for-line scripts.  Here is a little of my "deep background" thinking about the issue in particular and about how to get the most out of EE in general.

First, assumptions about the relative performance of a data base table vs a file-system lock are usually incomplete and often incorrect.  Too many factors are in play, among these, whether the DB server is on the same processor, how much memory is available, whether the I/O subsystem is RAID and cached, etc. etc.  In my experience, data base access, once the tables have been used, is amazingly fast - this has to do with the data being in a cache memory on the DB server.  So I do not buy the argument that a data base approach is slower or has more overhead than the file-system approach unless it can be demonstrated that it degrades throughput for the application.  Overhead does not matter if it is on a machine that is not in the way of transaction completion.  We did not have this kind of information available in this question, so my suggestion had to be made from my experience and some assumptions about what constitutes a thoughtful hosting server configuration.

Second, telling us you wouldn't feel comfortable doesn't really help us get you a better solution.  If it is because you do not understand the proposed logic or do not understand the use of a data base table in this context, we can help with that.  But we need a little more to go on.  Sometimes we find that a question has been posted saying, "It doesn't work" and that is sort of the same issue.  A little more detail can often get a much better answer.

Third, I'm not advising you out of a speculative posture or anything like that.  I do PHP / MySQL work for a living and I have a pretty strong instinct about what works and what does not.  Applications that have the ability to degrade gracefully and to recover from failed/faulty start schedules are kind of a "meets minimum" basic when you're dealing with the WWW.  I think that relying on the crontab to start jobs precisely on time has some inherent scheduling risk, and that is why I proposed backing up the chronological scheduling with a lock table in the data base, and with a garbage-collection script.

Fourth, you asked if "someone can review my script" and of course the answer is "yes" - it is always a good idea to get an extra set of eyes on the code.  I was actually expecting and hoping that you would post a more complete code sample.

Anyway, we gave the best advice we could with the information you gave us.  Going forward, it's probably better to err on the side of more dialog with the community rather than less.  Best regards, ~Ray
m002_parryAuthor Commented:
Ray, no disrespect to you but I think sometimes clarification on both sides would have helped the issue here. I appreciate the responses given in all circumstances and would not wish to suggest otherwise, however maybe its just me but explaining what you dont know is difficult for a beginner compared to an expert for argument sake.

I accept maybe it appears that I was not communicating enough, but what was proposed I couldnt see where to even begin with my script in relation to integrating it, hence my question "would anyone review my entire script to see the weaknesses and give expert opinions / examples".

If that is still possible, then I retract my original comments and feedback fully, but I got the impression no one would look at a full script, instead only snippets which in my opinion dont solve the issue for me. From what Ive gathered of PHP coding, it simply is about the "bigger picture" more often than not.

I will try harder in the future to try be more specific, feedback taken onboard.

If anyone is interested to see my wonderful amount of no doubt basic errors in coding, I attach the script I refer to in the above question.

Thanks again to everyone.

Guy Hengel [angelIII / a3]Billing EngineerCommented:
2 coding tips that can save hours of debugging:
§ make sure you indent the code,
§ comment the closing } from where they come from

if (somecondition)
  foreach ( ... )
  } // foreach (... )
else // if (condition)
   switch ( ... )  
      case ....:
           break; // case ....
      case ....:
           break; // case ....
   }  // switch ( ... )
} // else (condition)

Open in new window

Ray PaseurCommented:
@angelIII: That is advice that is worth many times the price of admission to EE.  

I might only add that although I am not religious about it, choosing and following a coding standard is VERY helpful.  The Zend standards are easy enough to live with:

And I also like to use plain spaces to separate and line-up code blocks - it makes for more readable code, no matter what the tabset might be for your text editor or IDE.

Also, I am a lazy programmer, and constructs that copy variable contents from one var to another like this:..

$cid = $p['id'];
$cip = $p['ip'];
$ctag = $p['tag'];
$cteam = $p['team'];
$cvip = $p['is_vip'];
$cping = $p['ping'];
$cscore = $p['score'];

 ... do not really seem to add value.  I do that sometimes for ease of coding when I need local variables, but I've often found that a change in the $p array leads to a bug in some other piece of my software because I forgot (or mistyped) the assignment statements.

Large blocks of code that are commented out with /* and */ might better be removed - too easy to spend time looking in the wrong place.

Whenever I see functions with a lot of global declarations, I always wonder if it would be better to consider OOP in the hope of avoiding future name collisions.

That's my $0.02, ~Ray
Guy Hengel [angelIII / a3]Billing EngineerCommented:

  do you want the question to be reopened, after the question seems to get on?

angel eyes
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.