I need to run a php script as daemon process (wait for instructions and do stuff). cron job will not do it for me because actions need to be taken as soon as instruction arrives. I know PHP is not really the best option for daemon processes due to memory management issues, but due to various reasons I have to use PHP in this case. I came across a tool by libslack called Daemon (http://libslack.org/daemon) it seems to help me manage daemon processes, but there hasn't been any updates in the last 5 years, so I wonder if you know some other alternatives suitable for my case. Any information will be really appreciated.
-
Related: http://stackoverflow.com/q/4717167/212218 – Jan 15 '12 at 21:43
-
1I came across this post http://gonzalo123.com/2010/05/23/building-network-services-with-php-and-xinetd/ which I belive is both relaxing and stable. – Teson Apr 22 '14 at 08:15
-
It's very easy to do with [systemd](https://stackoverflow.com/a/44420339/3706998) – LeonanCarvalho Mar 02 '18 at 12:59
15 Answers
You could start your php script from the command line (i.e. bash) by using
nohup php myscript.php &
the &
puts your process in the background.
Edit:
Yes, there are some drawbacks, but not possible to control? That's just wrong.
A simple kill processid
will stop it. And it's still the best and simplest solution.

- 36,243
- 17
- 80
- 100
-
1If the terminal exists the process will NOT exit. That's why the "nohup" command is there. I have been using a PHP script as daemon on all servers like just this for years now. There might be better solution, but this is the quickest one. – CDR Jan 15 '10 at 08:07
-
31This will not restart the daemon if it fails, and there is no easy way to manage the daemon at all. – Phil Wallach Jan 19 '10 at 05:33
-
6I agree with what's been said here-- this is a bad solution. You should create an init script for a couple of reasons: 1) Init script is launched automatically on startup 2) You can manage the daemon with start/stop/restart commands. Here is an example from servefault: http://serverfault.com/questions/229759/launching-a-php-daemon-from-an-lsb-init-script-w-start-stop-daemon – Simian Apr 02 '11 at 09:00
-
1hey guys ... it seems to me `nohup` and `&` does the same very thing: detaching the launched process from the current intance of the shell. Why do I need them both? Can I not just do `php myscript.php &` or `nohup myscript.php`?? Thanks – nourdine Mar 28 '14 at 09:04
-
To add some more clarity to this. `nohup` will make the script ignore a `SIGTERM` it will obviously still die with a `KILL`. You do need both, the `nohup` will make sure that if the parent process dies the script isn't taken with it, the `&` will make sure it will be pushed to the background as soon as it's called. In short this is a nice though hacky way to demonize and in PHP you're pretty much dependent on hacky ways for this use-case. – Thomas Jun 10 '14 at 16:51
-
1If the script writes to stdout (via echo or var_dump) then you can catch this information with a log file like this: `nohup php myscript.php > myscript.log &` – Mischa Feb 15 '16 at 22:41
-
-1: the advice here is poor and will result in a process not properly isolated from the controlling terminal, and giving rise to zombies. – symcbean Feb 13 '18 at 23:02
Another option is to use Upstart. It was originally developed for Ubuntu (and comes packaged with it by default), but is intended to be suitable for all Linux distros.
This approach is similar to Supervisord and daemontools, in that it automatically starts the daemon on system boot and respawns on script completion.
How to set it up:
Create a new script file at /etc/init/myphpworker.conf
. Here is an example:
# Info
description "My PHP Worker"
author "Jonathan"
# Events
start on startup
stop on shutdown
# Automatically respawn
respawn
respawn limit 20 5
# Run the script!
# Note, in this example, if your PHP script returns
# the string "ERROR", the daemon will stop itself.
script
[ $(exec /usr/bin/php -f /path/to/your/script.php) = 'ERROR' ] && ( stop; exit 1; )
end script
Starting & stopping your daemon:
sudo service myphpworker start
sudo service myphpworker stop
Check if your daemon is running:
sudo service myphpworker status
Thanks
A big thanks to Kevin van Zonneveld, where I learned this technique from.

- 18,229
- 10
- 57
- 56
-
2loving this. Just wondering, is it possible to have multiple concurrent workers? I just have the problem that one worker isn't enough any more. – Manuel Jul 02 '14 at 17:37
-
-
1
-
2Sudo "service myphpworker start" didn't work for me. I used "sudo start myphpworker" and it works perfectly – Matt Sich Jan 21 '15 at 01:00
-
1While executing "sudo service myphpworker start" its showing myphpworker: unrecognized service. – Pradeepta Jun 09 '15 at 07:34
-
3@Pradeepta That's because there is an error in the post - I'm not exactly sure what (and haven't tested this), but I think that `sudo service myphpworker start/stop/status` only works with services that are in `/etc/init.d` not upstart services. @matt-sich seems to have uncovered the correct syntax. Another option is to use Gearman or Resque, which allows background processing & deamonization. – ckm Jul 29 '15 at 19:33
-
I think this needs more upvotes! How can I start the script with sudo though, as in `$(exec sudo /usr/bin/php ...` this clearly doesn't work but my PHP script needs su rights, how can I do that? – php_nub_qq Sep 08 '15 at 08:57
-
@Manuel, you would want the main daemon to either fork() or spawn additional instances of itself or another script that runs as children. I generally have my main daemon managing multiple children when necessary. Because PHP doesn't allow these processes to really 'talk,' you have to get creative. I've had success using sockets, files, and databases for this purpose but sockets have been the easiest to work with. You simply pass a port to the child to connect to or have the child connect to a standard configurable port and report its PID to the parent. – DavidScherer Dec 14 '16 at 19:47
-
3Ubuntu itself is moving to using systemd instead of upstart: http://www.zdnet.com/article/after-linux-civil-war-ubuntu-to-adopt-systemd/ – Kzqai Mar 03 '17 at 03:33
-
-
@Jonathan How do I pass an argument to the .conf script? I would like that its remembered somewhere so that it uses those same parameters when the deamon automatically restarts. My goal is this: exec /usr/bin/php -f /path/to/your/script.php SOME_PARAM1 SOME_PARAM2 – Boy Oct 07 '17 at 05:11
With new systemd you can create a service.
You must create a file or a symlink in /etc/systemd/system/
, eg. myphpdaemon.service and place content like this one, myphpdaemon will be the name of the service:
[Unit]
Description=My PHP Daemon Service
#May your script needs MySQL or other services to run, eg. MySQL Memcached
Requires=mysqld.service memcached.service
After=mysqld.service memcached.service
[Service]
User=root
Type=simple
TimeoutSec=0
PIDFile=/var/run/myphpdaemon.pid
ExecStart=/usr/bin/php -f /srv/www/myphpdaemon.php arg1 arg2> /dev/null 2>/dev/null
#ExecStop=/bin/kill -HUP $MAINPID #It's the default you can change whats happens on stop command
#ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
StandardOutput=null #If you don't want to make toms of logs you can set it null if you sent a file or some other options it will send all PHP output to this one.
StandardError=/var/log/myphpdaemon.log
[Install]
WantedBy=default.target
You will be able to start, get status, restart and stop the services using the command
systemctl <start|status|restart|stop|enable> myphpdaemon
You can use the PHP native server using php -S 127.0.0.1:<port>
or run it as a script. Using a PHP script you should have a kind of "forever loop" to continue running.
<?php
gc_enable();//
while (!connection_aborted() || PHP_SAPI == "cli") {
//Code Logic
//sleep and usleep could be useful
if (PHP_SAPI == "cli") {
if (rand(5, 100) % 5 == 0) {
gc_collect_cycles(); //Forces collection of any existing garbage cycles
}
}
}
Working example:
[Unit]
Description=PHP APP Sync Service
Requires=mysqld.service memcached.service
After=mysqld.service memcached.service
[Service]
User=root
Type=simple
TimeoutSec=0
PIDFile=/var/run/php_app_sync.pid
ExecStart=/bin/sh -c '/usr/bin/php -f /var/www/app/private/server/cron/app_sync.php 2>&1 > /var/log/app_sync.log'
KillMode=mixed
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=default.target
If your PHP routine should be executed once in a cycle (like a diggest) you may use a shell or bash script to be invoked into systemd service file instead of PHP directly, for example:
#!/usr/bin/env bash
script_path="/app/services/"
while [ : ]
do
# clear
php -f "$script_path"${1}".php" fixedparameter ${2} > /dev/null 2>/dev/null
sleep 1
done
If you chose these option you should change the KillMode to mixed
to processes, bash(main) and PHP(child) be killed.
ExecStart=/app/phpservice/runner.sh phpfile parameter > /dev/null 2>/dev/null
KillMode=process
This method also is effective if you're facing a memory leak.
Note: Every time that you change your "myphpdaemon.service" you must run `systemctl daemon-reload', but do worry if you do not do, it will be alerted when is needed.

- 1,819
- 3
- 20
- 39
-
14
-
2Awesome. Wish we could heart answers too because this should not be buried on this page. – Justin Sep 25 '17 at 00:30
-
Hey, I am trying to do systemctl stop servicename but the php file keeps outputting to file .. I am working off of the "working example" file. – ScipioAfricanus Jan 11 '18 at 18:00
-
@ScipioAfricanus Maybe your are with ignoring user abort enabled in your php. – LeonanCarvalho Jan 11 '18 at 18:12
-
Hey, thanks for the tip but .. service still doesnt stop. I copied the php code verbatum, and when I do ps -ef | grep php this is what I get user 14020 1 0 13:03 ? 00:00:00 /bin/sh -c /usr/bin/php -f /app/folder/test.php 2>&1 > /app/folder/log.out user 14021 14020 0 13:03 ? 00:00:00 /usr/bin/php -f /app/folder/test.php The only change I made to the pid controller is I set user and group to some value. I tried it with root first, ofc, no difference. – ScipioAfricanus Feb 07 '18 at 18:04
-
1You should check `systemctl status
-l` output, it will give you a clue whats happening. – LeonanCarvalho Feb 07 '18 at 18:08 -
-
For ubuntu, mysqld is mysql, and memcache must be installed before. Also is more practical use a symlink to something like /var/www/daemons/myservice.service – Leandro Bardelli Aug 16 '18 at 20:09
-
1@LeandroTupone The MySQL and Memcached was a demonstration of how to use service dependencies it's not necessary. – LeonanCarvalho Aug 17 '18 at 13:11
-
-
1@LeandroTupone You should refer any services that your PHP server depends on, just to prevent failure but it's not necessary. – LeonanCarvalho Aug 17 '18 at 15:35
-
thanks for all your help. How could you put this as autostart? – Leandro Bardelli Aug 17 '18 at 18:25
-
1
-
I've several issues to stop the daemon, even with execStop, php will run forever and wont stop, multiple scripts will run at the same time with concurrence problems – Leandro Bardelli Aug 21 '18 at 20:27
-
1@LeandroTupone If your service start sub-scripts you should try other configuration for `KillMode` and `ExecStop` https://www.freedesktop.org/software/systemd/man/systemd.kill.html – LeonanCarvalho Aug 22 '18 at 13:23
-
3
-
1I am surprised how this is not the accepted answer... Best solution as of 2020 – Armedin Kuka May 04 '20 at 02:58
-
-
1`PIDFile=` not needed if used `Type=simple`. https://www.freedesktop.org/software/systemd/man/systemd.service.html#PIDFile= – Pavel A. Feb 08 '22 at 08:43
-
-
1
-
For linux systems running systemd, I would say this is the best answer. you've got my upvote for this. – Tuhin May 24 '22 at 09:22
-
One question, why choose a random number to call gc? presuming rand is seeded roughly one out of 20 iterations will call gc_collect_cycles(). Yes some obvious fluctuation but close. I'd say monitor the script and call gc based on your needs using a counter, such as `if(($counter++ % 20) == 0)` then tweak. – JSON Dec 11 '22 at 07:34
If you can - grab a copy of Advanced Programming in the UNIX Environment. The entire chapter 13 is devoted to daemon programming. Examples are in C, but all the function you need have wrappers in PHP (basically the pcntl and posix extensions).
In a few words - writing a daemon (this is posible only on *nix based OS-es - Windows uses services) is like this:
- Call
umask(0)
to prevent permission issues. fork()
and have the parent exit.- Call
setsid()
. - Setup signal processing of
SIGHUP
(usually this is ignored or used to signal the daemon to reload its configuration) andSIGTERM
(to tell the process to exit gracefully). fork()
again and have the parent exit.- Change the current working dir with
chdir()
. fclose()
stdin
,stdout
andstderr
and don't write to them. The corrrect way is to redirect those to either/dev/null
or a file, but I couldn't find a way to do it in PHP. It is possible when you launch the daemon to redirect them using the shell (you'll have to find out yourself how to do that, I don't know :).- Do your work!
Also, since you are using PHP, be careful for cyclic references, since the PHP garbage collector, prior to PHP 5.3, has no way of collecting those references and the process will memory leak, until it eventually crashes.

- 37,300
- 12
- 75
- 90
-
1Thanks for the info. It looks like libslack's daemon program pretty much does all the prep work like you mentioned. I think for now I'll stick with it until I find other good alternatives. – Beier Jan 11 '10 at 18:06
-
1Found this post, expected code to copy&paste into a crappy old application that fails to close stdin etc., was disappointed. :p – ThiefMaster Nov 18 '13 at 00:58
-
1
-
-
For future readers asking why to fork twice: https://stackoverflow.com/questions/881388/what-is-the-reason-for-performing-a-double-fork-when-creating-a-daemon -- TL;DR: Prevents zombies. – Ghedipunk Oct 19 '15 at 20:33
-
@Ghedipunk I read some answers at the link you posted, and I would say that a double fork is also used to prevent the second child to open a TTY terminal. You will prevent zombies too if you fork once cause the first child will become a child of `init` and will be cleaned up upon its execution by `init`'s periodical `wait` system calls. – tonix Jun 19 '16 at 14:23
I run a large number of PHP daemons.
I agree with you that PHP is not the best (or even a good) language for doing this, but the daemons share code with the web-facing components so overall it is a good solution for us.
We use daemontools for this. It is smart, clean and reliable. In fact we use it for running all of our daemons.
You can check this out at http://cr.yp.to/daemontools.html.
EDIT: A quick list of features.
- Automatically starts the daemon on reboot
- Automatically restart dameon on failure
- Logging is handled for you, including rollover and pruning
- Management interface: 'svc' and 'svstat'
- UNIX friendly (not a plus for everyone perhaps)

- 27,509
- 17
- 111
- 155

- 3,318
- 20
- 19
You can
- Use
nohup
as Henrik suggested. - Use
screen
and run your PHP program as a regular process inside that. This gives you more control than usingnohup
. - Use a daemoniser like http://supervisord.org/ (it's written in Python but can daemonise any command line program and give you a remote control to manage it).
- Write your own daemonise wrapper like Emil suggested but it's overkill IMO.
I'd recommend the simplest method (screen in my opinion) and then if you want more features or functionality, move to more complex methods.

- 71,383
- 13
- 135
- 169
There is more than one way to solve this problem.
I do not know the specifics but perhaps there is another way to trigger the PHP process. For instance if you need the code to run based on events in a SQL database you could setup a trigger to execute your script. This is really easy to do under PostgreSQL: http://www.postgresql.org/docs/current/static/external-pl.html .
Honestly I think your best bet is to create a Damon process using nohup. nohup allows the command to continue to execute even after the user has logged out:
nohup php myscript.php &
There is however a very serious problem. As you said PHP's memory manager is complete garbage, it was built with the assumption that a script is only executing for a few seconds and then exists. Your PHP script will start to use GIGABYTES of memory after only a few days. You MUST ALSO create a cron script that runs every 12 or maybe 24 hours that kills and re-spawns your php script like this:
killall -3 php
nohup php myscript.php &
But what if the script was in the middle of a job? Well kill -3 is an interrupt, its the same as doing a ctrl+c on the CLI. Your php script can catch this interrupt and exit gracefully using the PHP pcntl library: http://php.oregonstate.edu/manual/en/function.pcntl-signal.php
Here is an example:
function clean_up() {
GLOBAL $lock;
mysql_close();
fclose($lock)
exit();
}
pcntl_signal(SIGINT, 'clean_up');
The idea behind the $lock is that the PHP script can open a file with a fopen("file","w");. Only one process can have a write lock on a file, so using this you can make sure that only one copy of your PHP script is running.
Good Luck!
Kevin van Zonneveld wrote a very nice detailed article on this, in his example he makes use of the System_Daemon
PEAR package (last release date on 2009-09-02).

- 151,645
- 95
- 393
- 500
Check out https://github.com/shaneharter/PHP-Daemon
This is an object-oriented daemon library. It has built-in support for things like logging and error recovery, and it has support for creating background workers.

- 3,263
- 5
- 26
- 30
I recently had a need for a cross-platform solution (Windows, Mac, and Linux) to the problem of running PHP scripts as daemons. I solved the problem by writing my own C++ based solution and making binaries:
https://github.com/cubiclesoft/service-manager/
Full support for Linux (via sysvinit), but also Windows NT services and Mac OSX launchd.
If you just need Linux, then a couple of the other solutions presented here work well enough and, depending on the flavor. There is also Upstart and systemd these days, which have fallbacks to sysvinit scripts. But half of the point of using PHP is that it is cross-platform in nature, so code written in the language has a pretty good chance of working everywhere as-is. Deficiencies start showing up when certain external native OS-level aspects enter the picture such as system services, but you'll get that problem with most scripting languages.
Attempting to catch signals as someone here suggested in PHP userland is not a good idea. Read the documentation on pcntl_signal()
carefully and you will quickly learn that PHP handles signals using some rather unpleasant methods (specifically, 'ticks') that chew up a bunch of cycles for something rarely seen by processes (i.e. signals). Signal handling in PHP is also only barely available on POSIX platforms and support differs based on the version of PHP. It initially sounds like a decent solution but it falls pretty short of being truly useful.
PHP has also been getting better about memory leak issues as time progresses. You still have to be careful (the DOM XML parser tends to leak still) but I rarely see runaway processes these days and the PHP bug tracker is pretty quiet by comparison to the days of yore.

- 2,274
- 24
- 20
you can check pm2 here is, http://pm2.keymetrics.io/
create a ssh file, such as worker.sh put into your php script that you will deal with.
worker.sh
php /path/myscript.php
daemon start
pm2 start worker.sh
Cheers, that is it.

- 31
- 1
As others have already mentioned, running PHP as a daemon is quite easy, and can be done using a single line of command. But the actual problem is keeping it running and managing it. I've had the same problem quite some time ago and although there are plenty of solutions already available, most of them have lots of dependencies or are difficult to use and not suitable for basic usages. I wrote a shell script that can manage a any process/application including PHP cli scripts. It can be set as a cronjob to start the application and will contain the application and manage it. If it's executed again, for example via the same cronjob, it check if the app is running or not, if it does then simply exits and let its previous instance continue managing the application.
I uploaded it to github, feel free to use it : https://github.com/sinasalek/EasyDeamonizer
EasyDeamonizer
Simply watches over your application (start, restart, log, monitor, etc). a generic script to make sure that your appliation remains running properly. Intentionally it uses process name instread of pid/lock file to prevent all its side effects and keep the script as simple and as stirghforward as possible, so it always works even when EasyDaemonizer itself is restarted. Features
- Starts the application and optionally a customized delay for each start
- Makes sure that only one instance is running
- Monitors CPU usage and restarts the app automatically when it reaches the defined threshold
- Setting EasyDeamonizer to run via cron to run it again if it's halted for any reason
- Logs its activity

- 323
- 2
- 14
I was looking for a simple solution without having to install additional stuff and compatible with common hostings that allow SSH access.
I've ended up with this setup for my chat server:
-rwxr-xr-x 1 crazypoems psacln 309 ene 30 14:01 checkChatServerRunning.sh
-rw-r--r-- 1 crazypoems psacln 3018 ene 30 13:12 class.chathandler.php
-rw-r--r-- 1 crazypoems psacln 29 ene 30 14:05 cron.log
-rw-r--r-- 1 crazypoems psacln 2560 ene 29 08:04 index.php
-rw-r--r-- 1 crazypoems psacln 2672 ene 30 13:29 php-socket.php
-rwxr-xr-x 1 crazypoems psacln 310 ene 30 14:04 restartChatServer.sh
-rwxr-xr-x 1 crazypoems psacln 122 ene 30 13:28 startChatServer.sh
-rwxr-xr-x 1 crazypoems psacln 224 ene 30 13:56 stopChatServer.sh
And the scripts:
startChatServer.sh
#!/bin/bash
nohup /opt/plesk/php/5.6/bin/php -q /var/www/vhosts/crazypoems.org/httpdocs/chat/php-socket.php > /dev/null &
stopChatServer.sh
#!/bin/bash
PID=`ps -eaf | grep '/var/www/vhosts/crazypoems.org/httpdocs/chat/php-socket.php' | grep -v grep | awk '{print $2}'`
if [[ "" != "$PID" ]]; then
echo "killing $PID"
kill -9 $PID
else
echo "not running"
fi
restartChatServer.sh
#!/bin/bash
PID=`ps -eaf | grep '/var/www/vhosts/crazypoems.org/httpdocs/chat/php-socket.php' | grep -v grep | awk '{print $2}'`
if [[ "" != "$PID" ]]; then
echo "killing $PID"
kill -9 $PID
else
echo "not running"
fi
echo "Starting again"
/var/www/vhosts/crazypoems.org/httpdocs/chat/startChatServer.sh
And last but not least, I have put this last script on a cron job, to check if the "chat server is running", and if not, to start it:
Cron job every minute
-bash-4.1$ crontab -l
* * * * * /var/www/vhosts/crazypoems.org/httpdocs/chat/checkChatServerRunning.sh > /var/www/vhosts/crazypoems.org/httpdocs/chat/cron.log
checkChatServerRunning.sh
#!/bin/bash
PID=`ps -eaf | grep '/var/www/vhosts/crazypoems.org/httpdocs/chat/php-socket.php' | grep -v grep | awk '{print $2}'`
if [[ "" != "$PID" ]]; then
echo "Chat server running on $PID"
else
echo "Not running, going to start it"
/var/www/vhosts/crazypoems.org/httpdocs/chat/startChatServer.sh
fi
So with this setup:
- I manually can control the service with the scripts when needed (eg: maintenance)
- The cron job will start the server on reboot, or on crash

- 2,588
- 2
- 31
- 39
I wrote and deployed a simple php-daemon, code is online here
https://github.com/jmullee/PhpUnixDaemon
Features: privilege dropping, signal handling, logging
I used it in a queue-handler (use case: trigger a lengthy operation from a web page, without making the page-generating php wait, i.e. launch an asynchronous operation) https://github.com/jmullee/PhpIPCMessageQueue

- 390
- 3
- 6
Extending Emil Ivaov answer, You can do the following to close STDIN, STDOUT AND STDERROR in php
if (!fclose(STDIN)) {
exit("Could not close STDIN");
}
if (!fclose(STDOUT)) {
exit("Could not close STDOUT");
}
if (!fclose(STDERR)) {
exit("Could not close STDERR");
}
$STDIN = fopen('/dev/null', 'r');
$STDOUT = fopen('/dev/null', 'w');
$STDERR = fopen('/var/log/our_error.log', 'wb');
Basically you close the standard streams so that PHP has no place to write. The following fopen
calls will set the standard IO to /dev/null
.
I have read this from book of Rob Aley - PHP beyond the web

- 8,716
- 9
- 60
- 102