I have a PHP website in which, when a member visits a page, a series of database maintenance actions are made.
For example, in a common page, I've included a PHP script which checks how many posts every user has made and updates the database giving them points accordingly.
The problem with this method is that my website has 100+ members, and I'm worried that my scripts start to slow down as my memberbase grows.
Is there any way to code a bot in PHP, so my database can be updated without the user's intervention?
You should run a PHP file from within a cron job. Most PHP hosts including shared hosting provide cron access.
With cron you can schedule a task to run on an interval basis. This PHP program will then go through and do the updating that you require. So... take the code you do now and move it into a seperate PHP file and then tell cron to run it maybe once an hour or whatever you deem to be the correct interval.
For best performance, you need to update users table when he publish the post, not every time when need to know how many posts he published.
Create a cron to run daily (for instance) with the follow command:
php -q /home/cpaneluser/cron.php
And put a cron.php outside of public_html with all maintenance taks.
Or allow only administrators to do the maintenance tasks with a link in administrative panel.
Related
I'm working on an app written in CakePHp 2.3.8 on a Ubuntu 12.04 server running apache2. I'd like to create a cron job to handle a situation that occurs on the first day of every month. Each month users are given a set amount of specific tasks they can use, if they go over this limit they're charged based on the number of tasks they go over by. I'd like to create a cron job to accomplish this, but my concern is someone accessing the URL of the CakePHP action for this specific task which could then initiate financial transactions.
I read through this writeup from Google about cron jobs, but I'm not quite sure I understand what they're saying about securing URL's.
A cron handler is just a normal handler defined in app.yaml. You can prevent users
from accessing URLs used by scheduled tasks by restricting access to administrator
accounts. Scheduled tasks can access admin-only URLs. You can restrict a URL by
adding login: admin to the handler configuration in app.yaml.
If the URL being accessed is powered by my CakePHP app, how is cron able to determine whether or not an administrator is accessing it? Or am I supposed to write a stand-alone PHP (or whatever language) file to handle these cron jobs, and inside that file it can "talk" to cron to determine if an admin is accessing it?
Say I do use CakePHP to power it. Would it be safe (or rather necessary) to use a long string in the URL so that basically no one would guess it, and have it match that string in the code?
So something like www.mysite.com/url/to/task/jdbpojzm2929qJjfwX82j3zze9iwj919jsfjmmwmwi
And then my code for that job
function cron_called_function($code){
if($code == "jdbpojzm2929qJjfwX82j3zze9iwj919jsfjmmwmwi"){
//do task
}
}
Non-public member functions cannot be accessed via the url. Cake convention says prefix the method with an underscore.
private function _cron_called_function() { // or protected
// do task
}
Or perhaps look at creating a shell
and setting up a cron in cake
Never use URLs to do these kind of tasks, it is simply plain wrong, insecure and can cause your script to die or the server to become not responding any more.
Lets say you have 10000 users and a script runtime of 30 sec, it is very likely that the script times out before it finished and you end up with just a part of your users being processed at this time. The other scenario with a high or infinite amount of script runtime can lock your server. Depending on the script or DB actions it might cause the server to have a high load and users who use the site while the script is running will encounter a horrible slow to non responding site.
Also you can't really run a loop on a single URL, well you could redirect from one to another that does the limit and offset thing to simulate a loop over the 100000 users. If you don't loop over the records but fetch all 100000 at the same time it's likely your script dies because of running out of memory.
You should create a shell that processes the users in a loop and always just processes batches of for example 10, 50 or 100 users.
When executing your shell I recommend to use it with the "nice" command together to limit the amount of CPU time the shell is allowed to use to prevent the shell from taking 100% CPU usage to keep your site responding.
You can't "talk" to a cron either, a cron is nothing more than a timed executing of something. You can't really specify an user either except you implemented a shell in a way that allows you to pass a specific user as argument for example "cake transactions --user admin". If you mean to execute the shell with a specific system user see How to specify in crontab by what user to run script?.
Look at creating a shell
and setting up a cron in cake.
There are a bunch of ways to prevent anyone buy your own server from accessing a url. None are perfect, but some are better than others.
If possible, point the cron to a page that is simply not visible on the web. This could be a page that is located above the public_html heirarchy. From within the server, this page will be accessible, but will not be accessible via url. This is the best option, IMO.
Another option is to restrict the page to the ip address of the server and to other values in the request such as a post or querystring variable.
And, of course, you have already figured out that you can include a long secret or token in the url that would long enough to make it difficult or unlikely to guess.
You could also ping a page that, in turn, uses CURL to log in as an administrator and runs the page - this is, in some ways, the option that most reflects how you interact with the site. You could create a admin called "cron" and then there would be a log of "cron"'s activities just like any other admin. http://php.net/manual/en/book.curl.php
I want to be able to do few things using PHP: to setup CRON to run specific file at a specific moment (easy) and at the same time to get some sort of ID of that job, which would allow me to track/or cancel the job before it was even started. I would keep track of those IDs in my Database.
Messing directly with system files likes cron via PHP isn't really a good idea.
I would set up a master cron job file first which set up to run at every 5 mins and later will control all of your tasks
Build a solid database backend where you can store your tasks (script, start time, frequency etc.)
Build a panel where you can manage your tasks, start them, hold them, etc.
Check with your web-host. Besides running cron from the command-line or a script, some web management panels (like CPanel) has a graphical interface for setting up cron jobs.
I've got a database that processes an order - the Order is inserted at the beginning of the process but if the process is not complete (they left the page etc) the "confirmed" field is not filled in, this allows the admin to know which orders were complete or not.
At the moment I don't have the luxury of adjusting the way the website manages the data, I can however add some sort of weekly cleanout of these database fields where "confirmed" = 0.
How would I go about doing this automatically? Is there a way to run a query like this on a weekly, monthly, yearly basis?
Edit:
What if I added that the website is stored on a restricted, shared server where I have no access to the box itself?
You can use CRON to perform this job. But if you need to clean your database from incompleted orders only to show completed ones for humans and you don't export them to other places (e.g. manager visits backend once per day and looks for completed orders manually), i suggest you not to hire CRON for this. You can add few lines of code which will remove old entries from database each time backend was accessed.
DELETE queries are executed really fast so there will be no problems with perfomance. Real data deletion will be performed only by request. Also you don't need to have CRON (some cheap hosting providers do not give access to this service).
I usually create a PHP page that does the action and then schedule that to run using cURL and a CRON job.
If it's a Unix-like box, I'd put the cleanup in a PHP CLI script (that is, a PHP script that runs from the command line rather than in a web server module) and invoke that from a cronjob. Cron is a daemon for this exact purpose: Run things at predefined intervals. Cronjobs are defined in a crontab file, usually in /etc/crontab (for root) and ~/.crontab (for regular users); many distributions offer tools to safely edit this file.
Try man cron and man crontab for details. Also: http://en.wikipedia.org/wiki/Cron
setup a cron job and do a wget to run the script you want to automate. look at the link for more info http://www.phpmyvisites.us/faq/crontab-launch-automatically-statistics-archiving-process-every-62.html.
Write a short PHP script that updates/deletes the mysql records,
Then, if you have access to the linux/unix box, type crontab -e, you will then be prompted with the option to choose which editor you would like to view the current cronjobs, select the default and add this line:
0 0 * * 0 /usr/bin/php /path/to/script.php
Please check if /usr/bin/php exists before you set this up (you will need to install php-cli incase it does not exist, or the file might be also at /usr/sbin/php).
This cronjob will run once a week, if you want to change the frequency, use the manpages to learn how.
Also, are you sure you would like to run this script automatically? from what I understand you will need someone to first see the incomplete orders and only then to clean them up. if you run this cronjob you might be in a situation where someone did not complete his order but any evidence to that was deleted.
Hope this helps,
i wonder how can i schedule and automate tasks in PHP? can i? or is web server features like cron jobs needed.
i am wondering if there is a way i can say delete files after say 3 days when the file are likely outdated or not needed
PHP natively doesn't support automating tasks, you have to build a solution yourself or search google for available solutions. If you have a frequently visited site/page, you could add a timestamp to the database linking to the file, when visiting your site in a chosen time (e.g. 8 in the morning) the script (e.g. deleteOlderDocuments.php) runs and deletes the files that are older.
Just an idea. Hope it helps.
PHP operates under the request-response model, so it won't be the responsibility of PHP to initiate and perform the scheduled job. Use cron, or make your PHP site to register the cron jobs.
(Note: the script that the job executes can be written in PHP of course)
In most shared hosting environments, a PHP interpreter is started for each page request. This means that for each PHP script in said environment, all that script will know about is the fact that it's handling a request, and the information that request gave it. Technically you could check the current time in PHP and see if a task needs to be performed, but that is relying on a user requesting that script near a given time.
It is better to use cron for such tasks. especially if the tasks you need performed can be slow -- then, every once in a while, around a certain time, a user would have a particularly slow response, because them accessing a script caused the server to do a whole bunch of scheduled stuff.
I am writing a component for Joomla and there is a specific task that requires an update to some stats every so often. I would like to setup a cron job to do this. The only problem is that requires the user to go and setup the cron to run the php update stats script.
On installation of the component how can I automatically setup a cron job for the user? Is this possible?
I've seen this implemented in the Akeeba backup pro component for Joomla, so I was hoping that I would be able to do the same thing.
Thanks
In theory you can create a crontab file and call it from PHP
<?php
exec("crontab $path_to_cron_file");
in practice it depends on wether the server (if you're on a shared hosting) allows you to do that.
All you need to do is write a line to the crontab file, generally stored in /var/spool/cron/crontabs/username. The cron daemon will see that the file modification time has changed and reload it automatically when it wakes up to do its checks
Another option (less desirable from a server load perspective but easier for users) would be to create a plugin that is run each time a visitor visits the site. It could check whether the process has been run in a specified time and then run it if it needs to be run.
iJoobi.com has another solution where they have set up a server to run cron tasks, which would then ping the specific URL on the website to kick off the process. (http://www.ijoobi.com/Help/jNews/jNews-Cron-Task.html)