I'm working on creating some scheduled tasks that perform system maintenance on my database (i.e. inactive user cleanup, data archiving, etc.) and also generate/email automated data reporting.
Currently I have it setup so that each task is its own file and there is a master file that calls the appropriate tasks.
For example:
run_daily.php
<?php
define('INCLUDE_CHECK',true);
require $_SERVER['DOCUMENT_ROOT'].'/db/connect.db.php';
require $_SERVER['DOCUMENT_ROOT'].'/includes/definitions.inc.php';
$get_dailyTasks = mysql_query("SELECT task_name FROM task_scheduler WHERE task_type='task' AND task_occurs='daily' AND task_active=1");
while(($dailyTasks = mysql_fetch_assoc($get_dailyTasks)))
{
include $schedule.'tasks/'$dailyTasks['task_name'].$tsk;
};
$get_dailyReports = mysql_query("SELECT task_name FROM task_scheduler WHERE task_type='report' AND task_occurs='daily' AND task_active=1");
while(($dailyReports = mysql_fetch_assoc($get_dailyReports)))
{
include $schedule.'reports/'.$dailyReports['task_name'].$rbf;
};
?>
user_cleanup.php
<?php
$disable_inactive = "UPDATE users SET enabled='no' WHERE (created < (CURDATE() - INTERVAL 3 MONTH) AND last_active IS NULL AND enabled='yes') OR (last_active < (CURDATE() - INTERVAL 3 MONTH) AND enabled='yes')";
mysql_query($disable_inactive);
?>
I'm attempting to set it up this way because I plan on having the master file run via command line and scheduled as a task scheduler job on the server. I will have access to modify the files as needed but I will not easily be able to change what is scheduled to run once it is setup. My thought was to schedule a master task and this would allow me to add/remove sub-tasks as needed.
The problem I'm running into though is that when I test everything via command line, the sub-task never seems to return control to the main task. After the first sub-task runs (regardless of how I order them) none of the other sub-tasks after it run.
Related
I have a mysql table and I want it to be "emptied" every night at midnight. I have searched for an answer on the web and came across nothing that seemed to help me. I had this idea of using javascript to get the current time and then run an if statement and see if it is equal to midnight and if it was to execute a php script that deleted the information.
Javascript:
var myVar=setInterval(function(){myTimer()},1000);
function myTimer()
{
var d=new Date();
var t=d.toLocaleTimeString();
if(t == 12:00:00 AM){
$.ajax({
URL: 'delete.php';
});
};
};
delete.php:
<?php
require 'connect.php';
mysql_query("DELETE * FROM messages;");
?>
I have tested this by setting the time in the if statement to a time a few minutes ahead of my actual time and it does not work.
Implementing your own event scheduler, especially as a web page using JavaScript is a bad idea.
Use for that either
a cron job to run DELETE statement through the mysql command line interface
/path/to/mysql -u<user> -p"<password>" <db_name> -e "delete from messages"
or a MySQL event, e.g.
CREATE EVENT delete_messages_at_midnight
ON SCHEDULE EVERY 1 DAY STARTS CURDATE() + INTERVAL 1 DAY
DO DELETE FROM messages;
If you go with MySQL event approach:
use SHOW PROCESSLIST to check if the event scheduler is enabled. If it's ON you should see a process "Daemon" by user "event_scheduler".
use SET GLOBAL event_scheduler = ON;to enable the scheduler if it's currently not enabled.
More on configuring event scheduler read here
I usually update my site "by hand", entering in one page called "enterheretoupdate.php". This page refreshes every minute to do all the job I need, so while this page is "open", my site keeps refreshing every minute.
What does "enterheretoupdate.php" do? It makes things related to mysql: create tables, selects from tables, add rows to tables, etc. Apart from that, it also make calculations on php and updates .json files.
I would like to create a cron job, so that it is not necessary for me to visit "enterheretoupdate.php" on my computer for updating my site every minute.
I am quite new on this, but I have learned how to create a cron job (I use 1and1). The example cron job I have created, consisting on sending an email every minute, works fine.
But then, I tried to save "enterheretoupdate.php" as a cron job and it does not work. Is there a "limitation" on the things a cron job can do? How should I "translate" my php file to make it work as a cron job?
Any help is really welcome.
This is how my .php file looks like:
<?php
$page = $_SERVER['PHP_SELF'];
$sec = "10";
//Change 1 to reload, 0 to not to reload;
$reload=1;
$gamecode=7;
$cmp="EL";
$year=2017;
if ($reload==1) echo"<head><meta http-equiv='refresh'content=".$sec.";URL='".$page."?gamecode=".$gamecode."&cmp=".$cmp."&year=".$year."'></head>";
include("../newcon.php");
include("../formulas.php");
include_once("funLightCreateTables.php");
include_once("funLightFirstFive.php");
include_once("funLightChanges.php");
include_once("funLightLiveJsons.php");
if ($cmp=="EC") {$l="U";}
if ($cmp=="EL") {$l="E";}
//Check
$q="SELECT * FROM LightLiveSchedule WHERE year=".$year." and cmp=".$cmp." and gamecode=".$gamecode."";
$res=mysqli_query($link,$q);
while ($r=mysqli_fetch_assoc($res)){
$started=$r['started'];
}
if ($started==0){
LightCreateTables($cmp,$year,$gamecode);
$q="UPDATE LightLiveSchedule SET started=1 WHERE year=".$year." and cmp=".$cmp." and gamecode=".$gamecode."";
mysqli_query($link,$q);
}
//Read
$pbp=file_get_contents("http://thesite.com/data.json?gamecode=".$gamecode."&seasoncode=".$l.$year."");
$pbp = json_decode($pbp,true);
//Insert
mysqli_query($link,"Truncate P_Live_Temp_".$cmp."_".$year."_".$gamecode."");
$lres=0;
$vres=0;
$n=0;
for ($i=0;$i<=4;$i++){
$nplays[$i]=count($pbp[$qtitle[$i]]);
$ii=0;
for ($j=0;$j<=$nplays[$i];$j++){
//change results
if ($pbp[$qtitle[$i]][$ii]['PUNTOS_A']!=null) {
$lres=$pbp[$qtitle[$i]][$ii]['PUNTOS_A'];
}
if ($pbp[$qtitle[$i]][$ii]['PUNTOS_B']!=null) {
$vres=$pbp[$qtitle[$i]][$ii]['PUNTOS_B'];
}
//clean
if (strpos($pbp[$qtitle[$i]][$ii]['CSDESCWEB'],"(")==0) {$play=$pbp[$qtitle[$i]][$ii]['CSDESCWEB'];}
if (strpos($pbp[$qtitle[$i]][$ii]['CSDESCWEB'],"(")>0) {$play=substr($pbp[$qtitle[$i]][$ii]['CSDESCWEB'],0,strpos($pbp[$qtitle[$i]][$ii]['CSDESCWEB'],"(")-1);}
//count
$points=0;
if ($play=="Three Pointer") {$points=3;}
if ($play=="Two Pointer" or $play=="Lay Up" or $play=="Dunk") {$points=2;}
if ($play=="Free Throw In") {$points=1;}
//ntconsole=00:00 at End Game
if ($play=="End Game") {$pbp[$qtitle[$i]][$ii]['NTCONSOLA']="00:00";}
//insert
$q="INSERT INTO P_Live_temp_".$cmp."_".$year."_".$gamecode."
(orden,shteam,shloc,shvis,quarter,minute,ntconsole,pcode,play,locres,visres,points)
VALUES
(".$n.",'".$pbp[$qtitle[$i]][$ii]['NTEQUIPO']."','".$pbp['ca']."','".$pbp['cb']."',".($i+1).",
".$pbp[$qtitle[$i]][$ii]['MINUTO'].",'".$pbp[$qtitle[$i]][$ii]['NTCONSOLA']."',
'".str_replace(" ","",substr($pbp[$qtitle[$i]][$ii]['NTJUGD'],1,10))."','".$play."',".$lres.",".$vres.",".$points.")";
mysqli_query($link,$q);
$ii++;
$n++;
}
}
Do you think it is suitable for a cron job? How should I proceed? Thanks a lot!
I had similar issues but the following worked for me.
See the link to change default mysql permission
How to allow remote connection to mysql
Now change your db_server value in the sql connection file from
localhost to 127.0.0.1
In your case the you need to edit the file ../newcon.php it seems.
This is more of a logic question than language question, though the approach might vary depending on the language. In this instance I'm using Actionscript and PHP.
I have a flash graphic that is getting data stored in a mysql database served from a PHP script. This part is working fine. It cycles through database entries every time it is fired.
The graphic is not on a website, but is being used at 5 locations, set to load and run at regular intervals (all 5 locations fire at the same time, or at least within <500ms of each-other). This is real-time info, so time is of the essence, currently the script loads and parses at all 5 locations between 30ms-300ms (depending on the distance from the server)
I was originally having a pagination problem, where each of the 5 locations would pull a different database entry since i was moving to the next entry every time the script runs. I solved this by setting the script to only move to the next entry after a certain amount of time passed, solving the problem.
However, I also need the script to send an email every time it displays a new entry, I only want it to send one email. I've attempted to solve this by adding a "has been emailed" boolean to the database. But, since all the scripts run at the same time, this rarely works (it does sometimes). Most of the time I get 5 emails sent. The timeliness of sending this email doesn't have to be as fast as the graphic gets info from the script, 5-10 second delay is fine.
I've been trying to come up with a solution for this. Currently I'm thinking of spawning a python script through PHP, that has a random delay (between 2 and 5 seconds) hopefully alleviating the problem. However, I'm not quite sure how to run exec() command from php without the script waiting for the command to finish. Or, is there a better way to accomplish this?
UPDATE: here is my current logic (relevant code only):
//get the top "unread" information from the database
$query="SELECT * FROM database WHERE Read = '0' ORDER BY Entry ASC LIMIT 1";
//DATA
$emailed = $row["emailed"];
$Entry = $row["databaseEntryID"];
if($emailed == 0)
{
**CODE TO SEND EMAIL**
$EmailSent="UPDATE database SET emailed = '1' WHERE databaseEntryID = '$Entry'";
$mysqli->query($EmailSent);
}
Thanks!
You need to use some kind of locking. E.g. database locking
function send_email_sync($message)
{
sql_query("UPDATE email_table SET email_sent=1 WHERE email_sent=0");
$result = FALSE;
if(number_of_affacted_rows() == 1) {
send_email_now($message);
$result = TRUE;
}
return $result;
}
The functions sql_query and number_of_affected_rows need to be adapted to your particular database.
Old answer:
Use file-based locking: (only works if the script only runs on a single server)
function send_email_sync($message)
{
$fd = fopen(__FILE__, "r");
if(!$fd) {
die("something bad happened in ".__FILE__.":".__LINE__);
}
$result = FALSE;
if(flock($fd, LOCK_EX | LOCK_NB)) {
if(!email_has_already_been_sent()) {
actually_send_email($message);
mark_email_as_sent();
$result = TRUE; //email has been sent
}
flock($fd, LOCK_UN);
}
fclose($fd);
return $result;
}
You will need to lock the row in your database by using a transaction.
psuedo code:
Start transaction
select row .. for update
update row
commit
if (mysqli_affected_rows ( $connection )) >1
send_email();
I am a PHP/SQL novice user....Finishing off my first PHP website. The question is similar to the initial question found at:
http://forums.phpfreaks.com/topic/266235-modifying-database-after-a-set-time-limit/
but I did not completely understand the answer. Similar to that user, I have an entire column (called status) of a database (called challenge) that can take 3 values for status - 'inactive', 'pending', or 'active'. In the normal flow of website operations, User A will typically click a button (event 1) which creates a new row (with a unique *challenge_id*) in the database and triggers a status of 'pending' in that row. User B can change the status with other clicked buttons, which can set the status to 'inactive' or 'active'.
One undesirable scenario is where USER B does nothing (i.e., no event trigger). In this case, User A is unfortunately stuck, waiting for the status to change from 'pending' to either 'active' or 'inactive' before he/she can click and trigger the next event 1. This situation could occur for example if User B gets tired of the site and does not use it anymore, leaving 'pending' requests unanswered.
Clearly, I can manually alter the SQL, changing any 'pending' status to 'inactive' after a certain time limit. This would be fine at the beginning, but if the site ever became popular, this would take more time. Is there any way to write a non-PHP program to account for this 'no event trigger' scenario where all 'pending' status SQL entries are automatically altered after a certain time limit? Or can PHP do this? I tried writing a php script that would sweep the database every time any user logged in (note: *challenge_id* is created by an event triggered on a different PHP page):
<?php session_start();
if ((($_SESSION['role']) != SHA1('user')) && (($_SESSION['status']) != SHA1('active')))
{
header( 'Location: index.php' ) ;
session_destroy();
} else
include 'connect.php';
$_SESSION['login_id'];
$universaltime = time();
$sqlt = mysql_fetch_assoc(mysql_query("SELECT challenge.challengetime,
challenge.status FROM challenge"); //Selects an array of all values for challengetime
//and status for all users I presume
while ((($universaltime - $sqlt['challengetime']) > 1000) &&
($sqlt['status'] == 'pending'))
{
$sqlt1 = mysqli_query("UPDATE challenge SET $sqlt['status'] ='inactive'");
//Also tried with if instead of while
}
?>
I'm sure my code can be improved...any help would be appreciated greatly! Or do I need to use something other than PHP?
First of all your UPDATE statement is wrong. Assuming that challengetime is of int data type holding unix time values your UPDATE statements should look something like this
UPDATE challenge
SET status = 'inactive'
WHERE status = 'pending'
AND 1000 < UNIX_TIMESTAMP() - challengetime;
It can be and should be run on its own. You don't need to select anything prior to calling it.
Therefore you can change this part
$universaltime = time();
$sqlt = mysql_fetch_assoc(mysql_query("SELECT challenge.challengetime,
challenge.status FROM challenge"); //Selects an array of all values for challengetime
//and status for all users I presume
while ((($universaltime - $sqlt['challengetime']) > 1000) &&
($sqlt['status'] == 'pending'))
{
$sqlt1 = mysqli_query("UPDATE challenge SET $sqlt['status'] ='inactive'");
//Also tried with if instead of while
}
with just
$sql = "UPDATE challenge SET status = 'inactive' WHERE status = 'pending' AND 1000 < UNIX_TIMESTAMP() - challengetime";
$result = mysql_query($sql);
if (!$result) {
die('Invalid query: ' . mysql_error()); //TODO better error handling
}
Now to make it execute periodically on it own you don't necessarily need php. You can:
First option Use MySQL event.
To execute this statement every day at 11pm
CREATE EVENT change_status
ON SCHEDULE EVERY 1 DAY
STARTS CURDATE() + INTERVAL 23 HOUR
DO
UPDATE challenge
SET status = 'inactive'
WHERE status = 'pending'
AND 1000 < UNIX_TIMESTAMP() - challengetime;
Use SHOW PROCESSLIST to check if event scheduler is enabled. If it's ON you should see a process "Daemon" by user "event_scheduler".
Use SET GLOBAL event_scheduler = ON;to enable the scheduler if it's currently not enabled.
More on configuring event scheduler here
Second option Use crontab to invoke CLI mysql
/usr/local/mysql/bin/mysql -uuser -ppassword -e " UPDATE challenge SET status = 'inactive' WHERE status = 'pending' AND 1000 < UNIX_TIMESTAMP() - challengetime"
If your web & PHP server is running on Linux (which is often the case) and if the delay x is more than a few minutes (i.e. x>=5 minutes) then you could use crontab(1) and add a crontab(5) entry. Remember to use absolute paths there. That entry would run (periodically) some script (which you could code in PHP, but also in some other scripting language like Python or OCaml) which would update the MySQL database.
I wrote a PHP script to pull tweets from the Twitter firehose and store them into a database. Ideally I want to just let it run so that it collects tweets over time, thus, it's wrapped in a while(1) loop.
This seems to be problematic because it's timing out. If I just run it in a browser, it won't run for more than 30 seconds before timing out and giving me a 324 Error.
Question: Is there a way that I can have it run for a certain amount of time (20 seconds), auto kill itself, then restart? All in a cron job (PS...I don't know how to write a cron job)?
Background: Site hosted on Godaddy. Would ideally like to run this on my hosting server there.
The Script:
<?php
$start = time();
$expAddress = "HOSTNAME";
$expUser = "USERNAME";
$expPwd = "PASSWORD";
$database = "DBNAME";
$opts = array(
'http' => array(
'method' => "POST",
'content' => 'keywords,go,here',
)
);
// Open connection to stream
$db = mysql_connect($expAddress, $expUser, $expPwd);
mysql_select_db($database, $db);
$context = stream_context_create($opts);
while (1) {
$instream = fopen('https://USERNAME:PASSWORD#stream.twitter.com/1/statuses/filter.json','r' ,false, $context);
while(! feof($instream)) {
if(time() - $start > 5) { // break after 5 seconds
break;
}
if(! ($line = stream_get_line($instream, 100000, "\n"))) {
continue;
}
else {
$tweet = json_decode($line);
// Clean before storing
// LOTS OF VARIABLES FOR BELOW...REMOVED FOR READABILITY
// Send to database
$ok = mysql_query("INSERT INTO tweets
(created_at, from_user, from_user_id, latitude, longitude, tweet_id, language_code,
place_name, profile_img_url, source, text, retweet_count, followers_count,
friends_count, listed_count, favorites_count)
VALUES
(NOW(), '$from_user', '$from_user_id', '$latitude', '$longitude', '$tweet_id', '$language_code',
'$place_name', '$profile_img_url', '$source', '$text', '$retweet_count', '$followers_count',
'$friends_count', '$listed_count', '$favorites_count')");
if (!$ok) { echo "Mysql Error: ".mysql_error(); }
flush();
}
}
}
?>
You can have cron jobs run once a minute.
To do this follow these steps:
Make a script that runs your PHP code, for example:
#!/bin/bash
wget myurl.com/blah > /dev/null
Save it as my-cron.sh in some folder (like /var)
Add it to cron. Run crontab -e See Cron Format and Crontab usage.
This for example, will run it once a minute.
# Minute Hour Day of Month Month Day of Week Command
* * * * * /var/my-cron.sh
If I get well your need, the best thing for you is to use cron job making a script run indefinitely will not be a good idea.
As specifier in one of you comments you are using a hosting server Godaddy so probably you will not be able to have shell access, BUT depending on your cPanel version you may be able to create and define cron job.
see this link and this google search
Perhaps, if you don't have this option and you are wiling to let a browser opened I would suggest the following
create an html page as a client which would make an ajax request every hours to your PHP script, like this you emulate a cron job function
the ajax request code might look like (using jQuery)
function makeRequest(){
$.ajax({
url: "http://yourhost/url-to-your-script.php",
complete: function(data){
setTimeout(function(){
makeRequest();
}, 60 * 60 * 1000); // Minutes * Seconds * MS
}
});
}
makeRequest();
I hope this helps
EDIT
this link might help too
IMPORTANT DO NOT FORGET TO REMOVE THE INFINITE LOOP
I just had same issue.
Only cron job can do if you want run script off browser. You can set up cron job with free providers or you can set up cron job in windows's Scheduled tasks.
If your site has a good traffic then you can follow the option below that your users does the work for you.
In php you can find time in hour and seconds
$time= date(' H:i:s');
create a table to track if the code was run.
eg; table column name check with option 0 and 1;
select check from table.
enter code here
if ($minute > 59)
{
if($check==0)
{
run your code
then update the table each time when it was run
eg; update table set check='1'
}
}
then another if condition to reset your code
if(minute>0 && minute <1)
{
select check from your table.
if(check==1)
{
update table set check='0'
}
}