I have cron job - php script which is called one time in 5 minutes. I need to be sure that previously called php script has finished execution - do not want to mix data that's being processed.
There are three approaches I used to apply:
Creation of auxiliary text file which contains running-state flag. Executed script analyzes the contents of the file and breaks if flag is set to true. It's the simplest solution, but every time I create such script, I feel that I invented a bike one more time. Is there any well-known patterns or best-practices which would satisfy most of the needs?
Adding UNIX service. This approach is the best for the cron jobs. But it's more time consuming to develop and test UNIX service: good bash scripting knowledge is required.
Tracking processes using database. Good solution, but sometimes database usage is not encouraged and again - do not want to invent a bike, hope there is a good flexible solution already.
Maybe you have other suggestions how to manage single-processing of php scripts? Would be glad to hear your thoughts about this.
I'd recommend using the file locking mechanism. You create a text file, and you make your process lock it exclusively (see php flock function: http://us3.php.net/flock). If it fails to lock, then you exit because there is another instance running.
The advantage of using file locking is that if your PHP scripts dies unexpectedly or gets killed, it will automatically release the lock. This will not happen if you use plain text files for the status (if the script is set to update this file at the end of execution and it terminates unexpectedly, you will be left with untrue data).
http://php.net/flock with LOCK_EX should be enough in your case.
You could check wether or not your script is currently running using the ps command, helped by the grep command. "man ps" and "man grep" will tell you all about these unix/linux commands if you need informations about these.
Let's assume your script is called 'my_script.php'. This unix command :
ps aux | grep my_script.php
...will tell you if your script is running. You can run this command with shell_exec() at the start of your script, and exit() if it's already running.
The main advantage of this method is that it can't be wrong, where the script could have crashed, leaving your flag file in a state that would let you think it's still running.
I'd stick to version number 1. It's simple and works out. As long as you only wan't to check whether the script has finished or not it should be sufficent. If more complex data is to be remembered I'd go for version 3 in order to be able to 'memorize' the relevant data...
hth
K
Related
Are there any simple ways to run a PHP script when a file is added to a specific directory?
On linux there are perfect tools for this like inotify/dnotify, can't find any for Windows.
If I run a PHP script that loops infinitely - will that make a significant impact on cpu performance (if all it does is check folder for contents)?
I read that Win32::ChangeNotify could be used, but I'm a noob in Perl, so I have no idea how to set it up.
The easiest way to manage this would be to create a cron job that runs your script every minute (or however often you wish to check).
Edit - Just read the post again, and it hit me that you're using Windows. I suppose you can use Scheduled Tasks to do this.
In my php project i should have some background process , but in safe mode , because I'm running it on a shared host.
For example my background process code is in the file bg.php and I want it to be executed , write at finish of another specific script.( or maybe with some delay )
I searched a lot. some suggested libraries like beanstalkd but i think this library is heavy for my simple background process and also doesn't have good doc for PHP. some others said functions like exec() which is not possible in safe mode.
1- Does anyone have a simple solution for this problem?
2- I were also mentioned by cron jobs existing in cpanel which
prepare tasks to be executed on a specific time. can I use this
option to solve my problem in some way?
I noted I want a simple and lightweight solution. any suggestions appreciated deeply.
It's not possible use a PHP file served by a HTTP Server because all proceses will die after the request end.
So cPanel cron is a good option, you don't need to have the cron entry always enable, just setup once the entry and disable it after the script start to run.
Only you'll need add & at the end of your cron command to make it run as background.
The question is very easy, I want to execute several php files every "N" minutes. For example:
every N minutes
{
execute(script1.php)
execute(script2.php)
execute(script3.php)
}
I know about crontab but i was trying to find another solution. Any suggestions? Thanks in advance.
Using a Cron job is the usual solution. Can you explain why you don't want to use CRON? I've also seen libraries that add cron-like features to your system. For example in the Java/Groovy/Grails world there's the Quartz library/plugin. A quick Google search yielded a PHP library called phpJobScheduler that seems similar to Quartz. I have never used phpJobScheduler so I can't vouch for it.
I'd be interested in why you don't want to use crontabs for this? Are you going to be the primary web operations person running this server or will you be relying on an existing sysop team? You may want to get their input since they are the ones who will be most impacted by what method you choose. I've found they tend to be fond of cron for simple scheduling.
On windows I used built-in proggie called Task Scheduler. As for linux, yes, cron jobs is your answer.
You could create a php script to loop forever do X every N minutes and run the command with a & to make it a background process.
/path/to/php /home/user/bgscript.php &
If you want it to always run, you'd then have to add it to startup init.d or services depending on flavor of *nix.
This solution is possible but personally I would highly recommend going with crontab, its established, proven and works well! Why are you avoiding it?
You could build a script and let it run as a daemon and perform certain tasks on a set interval, but that's actually just simulating cron ... and if you have the ability to run a php script as a daemon you should really also be able to run it as a cronjob since that's what crons are made for.
If you need more info on how to run a php script as a daemon read this great intro. There is also a great comparison between daemon and cron inthere, worth the read.
I have StartServer.php file that basically starts a server if it is not already started. Everything works perfect except that the StartServer.php will hang forever waiting for the shell_exec()'d file Server.php to finish its execution that it never does.
Is there a way to execute a PHP file and just forget about it -- and not wait for its execution to finish?
Edit: It has to work on Windows and Linux.
This should help you - Asynchronous shell exec in PHP
Basically, you shell_exec("php Server.php > /dev/null 2>/dev/null &")
You'll need something like the pcntl functions. Only problem is that this is a non-windows extension, and not suitable to run inside a web server. The only other possibility I can think of is to use the exec function and fork the current process manually (as suggested in dekomotes's answer), doing OS detection to figure out the command needed. Note that this approach isn't much different to using the pcntl functions (in Linux, at least) - the ampersand character causes the second script to be run inside different process. Multi-threaded / multi-process programming isn't well supported in PHP, particularly when running inside a web server.
I think it's traditional to let the server detach itself form the parent process, ie to "daemonize" itself, rather than having the script starting the server detach itself. Check the server you're starting to see if it has a daemon-option.
If you've written the server yourself, in PHP, you need to detach it. It looks somehting like this:
posix_setsid(); //Start a new session
if(pcntl_fork()) {exit();} //Fork process and kill the old one
I think this works on Windows too. (Not tested.)
I have a PHP script that is called from a cron job every minute. This script takes some info from the database and then calls another PHP script using the System function (passing it some parameters).
That means that I can start up to 10 scripts from this "main" one. And what I would like to do is that I would call the script and continue the execution of the main script, that is, not wait for the System call to complete and then call the next one.
How can this be done?
You may be able to use proc_open(), stream_select() and stream_set_blocking() in concert to achieve this kind of thing.
If that sounds vague, I was going to paste a big chunk of code in here that I used in a recent project that did something similar, but then felt it may hinder rather than help! In summary though, the code worked like this:
cronjob calls cronjob_wrapper.php
cronjob_wrapper.php creates a new Manager class and then calls start on it.
Manager class start method check to see how many instances are running (looking for pid files in a particular location). If it's less than a given max number of instances it writes out it's own process id to a pid file and then carries on
Manage class creates an instance of an appropriate Encoder class and calls exec on it.
The exec method uses proc_open, stream_select and stream_set_blocking to run a system command in a non-blocking fashion (running ffmpeg in this case - and could take quite a while!)
When it has finally run it cleans up its PID file and bails out.
Now the reason I'm being vague and handwavy is that our multiple instances here are being handled by the cronjob not by PHP. I was trying to do very much the kind of thing you are talking about, and got something working pretty well with pcntl_fork() and friends, but in the end I encountered a couple of problems (if I recall at least one was a bug in PHP) and decided that this approach was a much more rock-solid way to achieve the same thing. YMMV.
Well worth a look at those functions though, you can achieve a lot with them. Though somehow I don't think PHP will ever become the sockets programming language of choice... :)
If your OS supports it, you can use the pcntl_fork() function to spin off child processes that the parent doesn't wait for. Be careful though, it is easy to accidentally create too many child processes, especially if they take longer than expected to run!
I think the answer would be very similar to those already provided for Asynchronous PHP calls.
http://php.net/pcntl_fork
It's *NIX only but you can fork your script using the PCNTL extension.
I'm not sure that PHP supports threading. Check here.
You could run them in the background:
system('php yourscript.php &');
You just have to make sure that you check on the total number of processes running. All in all, not a super elegant solution. Instead cron you could let one script run for forever, I am thinking something like this:
<?php
while(true) {
// do whatever needs to be done.
}
?>
Careful though. PHP is not exactly known to be used as a daemon.
use php's version of fork or threads.