WHAT ARE PHP DAEMONS, AND HOW DO YOU MAKE ONE?
PHP is often associated with HTML code generation, but it can also be used as a background application for handling and analysing data. Many popular web applications (like WordPress, osTicket and many others) make use of PHP scripts for background operations like database clean up, email and messages retrieval and statistical data analysis.
How do these kind of scripts work?

BACKGROUND AND FOREGROUND SCRIPTS
This kind of PHP scripts are different from “normal” ones, because they are not executed by the web server when someone visits a webpage. Instead, they are executed from the command line PHP interpreter without interacting with the web server.
Scripts executed from the web server usually output some HTML code, which is read by the web server itself and sent to the remote user browser. PHP scripts that run from the command line do not usually output HTML code, because their purpose is to perform background operations and data analysis instead of interacting with users.
The standard, HTML generating PHP scripts can be seen as “foreground scripts”, as their output is intended to be visible by users. The other kind of scripts can be called “background scripts” instead, underlining the fact that they are usually invisible to users and that they work regardless of HTTP requests.
Now you should be wandering: if there is no web server executing these background scripts, who does?
Usually, these scripts need to be executed at regular time intervals, for example once every hour or once a day. In Unix systems this is often done with CRON; if you are not familiar with Unix systems, you can think of CRON as a scheduler for launching applications (including PHP scripts) at specific times, at specific days of the week and so on.
For example, suppose you have a log database table and that you want to periodically delete logs older than one month. To do that, you can write a PHP script that deletes logs older than one month, and then configure CRON (or any other scheduler) to execute that script every day at a specific time.
Using a scheduler like CRON, however, has a few drawbacks. What if you need to dynamically change the execution time? What happens if the script is still being executed while the scheduler tries to run it again? And how could you do if you need to share informations between multiple executions of the script?
It is possible to address all this issues even when using CRON, but it’s very difficult and not very portable.
There is another solution: let the script itself iterate and never stop. Such a script is called a PHP daemon.
Here is a basic example:
<?php
/* Remove the execution time limit */
set_time_limit(0);
/* Iteration interval in seconds */
$sleep_time = 600;
while (TRUE)
{
/* Sleep for the iteration interval */
sleep($sleep_time);
/* Print the time (to the console) */
echo 'Time: ' . date('H:i:s');
}
This simple daemon prints the time every 10 minutes (600 seconds). You cannot execute it through a web server, as in that case the server would wait forever (or until a timeout) for the script to terminate. Instead, you need to execute it from the command line PHP interpreter, and every 10 minutes you would see the time printed on the console.
In this example you can see the two basic elements of a PHP daemon: an infinite loop (in this case, the while(TRUE) construct) and a sleep statement. The while loop lets the script run indefinitely, and the sleep statement sets the execution interval of the main code (in this case, the time output).
Without the sleep statement, the code would execute continuously using 100% of the CPU all the time, something you definitely do not want.
DAEMON EXAMPLE: AN EMAIL ALERT SYSTEM

Now let’s see a more realistic example.
Suppose we want to create an alert system. We need to implement a PHP script which will connect to a database and search a table for error messages. To keep things simple, let’s say that every record in this table contains an error message.
For every record found, the script needs to send an email to a specific address using PHPMailer (if you are not familiar with it please take a look at my PHPMailer tutorial).
However, we don’t want to send more than 10 emails per hour, even if there are more errors in the database, so the script must know when this limit is reached.
First we need to choose the iteration interval, that is how many seconds we want the sleep statement to pause the script at every iteration. This will determine how much often the script will check for errors and eventually send the alert emails. Let’s say 10 minutes is a good choice.
Then we just need to implement the alert logic.
Important: PHP daemons too need to pay attention to SQL security: be sure to read my SQL injection prevention guide to know how to stay safe from injection attacks.
Here is the script’s code:
<?php
/* Remove the execution time limit */
set_time_limit(0);
/* Include PHPMailer autoloader */
require_once './phpmailer/PHPMailerAutoload.php';
/* Iteration interval in seconds (10 minutes) */
$sleep_time = 600;
/* How many emails we already sent this hour */
$sent_emails = 0;
/* When we sent the last email */
$last_email_time = 0;
while (TRUE)
{
/* Sleep for the iteration interval */
sleep($sleep_time);
/* Retrieve errors from the database */
$errors = get_errors();
/* Send an email for each error */
foreach ($errors as $error)
{
/* If the last email was sent more that 1 hour ago, we reset the counter */
if (date('YmdH') !== date('YmdH', $last_email_time))
{
$sent_emails = 0;
}
/* We check how many emails we sent this hour */
if ($sent_emails < 10)
{
/* Ok, we can send another one */
send_error_email($error);
/* Increment the counter and set the last email time */
$sent_emails++;
$last_email_time = time();
}
}
/* Function to retrieve errors from database */
function get_errors()
{
$errors = array();
try
{
/* Connect to database (with PDO) */
$db = new PDO('mysql:host=localhost;dbname=test', '', '');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/* We suppose the "errors" table contains the errors we look for */
$sql = 'SELECT * FROM errors';
$st = $db->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$st->execute();
$res = $st->fetch(PDO::FETCH_ASSOC);
/* We add the error to the return array */
$errors[] = $res;
}
catch (PDOException $e)
{
/* Exception (SQL error) */
echo $e->getMessage();
die();
}
return $errors;
}
/* Function to send error emails (with PHPMailer) */
function send_error_email($error)
{
$mail = new PHPMailer();
$mail->setFrom('darth@empire.com', 'Darth Vader');
$mail->addAddress('palpatine@empire.com', 'The Emperor');
$mail->Subject = 'Error alert';
$mail->Body = 'New error detected: ' . print_r($error, TRUE);
$mail->send())
}
The sleep statement pauses the script execution for 10 minutes at every iteration. This time can be changed: for example, if we need to receive the alerts more quickly we can set the iteration interval to 5 minutes or even less. Keep in mind that the lower the iteration interval, the higher the system load becomes.
This example script doesn’t use much system resources, so the iteration time could even be set to 1 minute without problems. When implementing more complex scripts, however, you should be careful in choosing the right iteration time.
Notice how we used two “global” variables ($sent_emails and $last_email_time) to avoid sending more than 10 emails per hour. If we used a scheduler (like CRON) to execute a background script, we would need to keep this record on the database or in a file.
A good idea is to use a boolean variable for the while loop check, instead of just using TRUE. You can initialize the variable to TRUE, and set it to FALSE when, for some reason, you want the script to terminate.
In another post I will show you how can implement a “control panel” for monitoring the status of multiple PHP daemons and also pausing or stopping them.
That’s it. If you want some other example or have any questions just leave a comment below.
As always, I really thank you for reading this post, and if you liked it please take a second to share it!
Click the button below to download the example:
Alex
You really need to pagination or with more than 100 comments its just too much for user to scroll down to submite a comment
Hi,
Thank you for your suggestion. I just enabled pagination for comments (max 50 threads per page).
I am using GoDaddy hosting and have used the cron job facility to run a php script every hour. I can also run this at any time to force the updates…
Another way to do a daemon is to use ratchet php. It’s more complex to use, but u have much more flexibility.
Thank you for your suggestion, Tom.
Hallo thanks very much , With a php application am working on , i need to send email alerts to my clients on every 25th for each month ,
I need a working example from you on how i can implement this functionality using php deamons,
For those who are interested, we are talking about this here: https://www.facebook.com/groups/289777711557686/permalink/842449509623834/
The tutorial has the answers, you need to read it. Read it really. If you can’t understand it, you need to practice and make a simple local working copy. If you can’t understand your own code while you write it, then a job change is mandatory. Otherwise, if you need help, I could point you in the right direction, but don’t ask Alex to write code for you… it spends already time for writing such wonderful and easy to follow articles. You could find me on: rivdesign dot dev at gmail dot com
Have a great coding session and a wonderful day/night.
Hallo thanks very much , i need a detailed working example with this script,
How do i implement one?
Hi Alex, this is awesome. You have opened my eyes to new possibilities.
My question is, how do I restart the daemon from the dashboard after it has stopped?
Also how exactly do I make it begin executing?
To control the daemon you can see the answer below (“START AND STOP THE DAEMON”).
Anyway, I see that you have written on my FB group too, so I’ll answer you better there 🙂
Great article alex, been having issues with while loops, so i took time to read this wonderful article, my problem is how to see list of daemons running and stop them or pause them, and second i used to initialize my while loop using a form, something like
isset($_POST[‘submit’]{
$counter = 0;
while($counter < 10) {
echo ' i go';
Sleep(60);
}
This does what i want but it keep running until i turn off my local server and this is not something i can do in a shared hosting.
So i will love to know how to stop it, anytime i want to adjust something in the function.
I have tried everything from deleting the code, changing $counter to 10 and Every thing.
I need further guide please Alex especially regarding stopping it.
Thanks.
Hey Chris,
the solution is to use the database to control the PHP daemon.
You should create a database table that links each daemon with a set of values, so you can see what the daemon is doing and control it.
– LIST OF DAEMONS
Each daemon should have a name, or an ID.
At every loop, the daemon updates its row on the table setting its status (running, paused, stopped…) and the timestamp of the update.
This way, you can build a simple dashboard that looks all of the daemons status and the timestamp of their last iteration. From the dashboard, you can see what each daemon is doing.
– START AND STOP THE DAEMON
At each loop, each daemon will look in its table searching for a “command” message.
You can easily set these commands directly from your dashboard.
The daemon will decide what to do depending on the command. For example:
– “run”: keep looping and performing the operations.
– “pause”: keep iterating, but do not perform any operation.
– “exit”: stop the loop and exit.
You can add as many commands as you want, and also include more parameters. For example, you can set a command to increase the sleep time to a specific value.
Let me know if this helps.
Sure alex this helps in the sense that it gave me a sketch of the operations but frankly speaking i need a guide to it as how to stop the iteration, i can easily have these details inserted in my database but which command line will exist or stop the loop? Is there a php function that can stop the loop like global_loop_exist_function($loopname, exit)
You can implement such function.
Please, join my Facebook group so we can talk about that with more ease:
https://www.facebook.com/groups/289777711557686/
Thanks alex but am not a Facebook user, i only do whatsapp or email, and if you have a youtube channel where we can go watch the videos i can, please find time to give me sample functions to pause, exist or stop the while loop, i found using while loop better and reliable than cronjobs
If what you are saying is what am think then wont it overload my database if am query the database every 10mins.
This is what am think
$sql = (” SELECT * tablename WHERE column = daemon_id”);
while($sql == ‘run’){
// run my stuffs
echo ‘my stuff is running’;
sleep(600);
}
So if i want it to stop i will simply update the database table to stop.
Will this work? and secondly will this not over stress the database?
Thirdly the pause part is what i dont understand how to do it,
And i notice using break; exists the code on first run
Hi Chris,
in the link you can find a more detailed example.
Do not worry about overloading the database.
https://pastebin.com/asRwNX2H
So thankful alex, i followed the link and i got it working, fixed some database error connections in your source code and that place you concatenated the daemon name variable has error too, but i guess it was an omission, am so greatful alex. You are a life saver.
Yeah sorry for that, I fixed it now.
Anyway, I’m glad to know it worked for you!
Thank you for the good job. You did well. Can this be used to send mails to multiple users at the same time? Once again thank you.
Yes.
You can send the same email to many addresses with PHPMailer.
You can also send different emails to different addresses inside the daemon loop, by creating multiple $mail objects.
Here you can find my PHPMailer tutorial: https://alexwebdevelop.com/phpmailer-tutorial/
Clear, informative – and on a subject I never see discussed anywhere. Thank you!
Thank you for your comment, Steve.
“In another post I will show you how can implement a “control panel” for monitoring the status of multiple PHP daemons and also pausing or stopping them.”
When? I want this post 🙂
Best tutorial
Where is the follow up to this where you cover the “control panel” application to monitor the status of such Daemons?
okay, but how do you execute it the first (and supposedly only) time to make it start running?
Hi Germán,
PHP daemons are usually executed at boot time by a shell script.
Thank you ber much Mr. Alex. This is awesome tutorial.
Thanks Rakesh.
Salam Alaikum Mr Alex
Thank you very much
it was and is very useful for me
god(Allah) bless you
Thanks 🙂