execute external php via cron - php

I have a script on my shared hosting. When i execute the script it checks if there are new members on the site. If so, the script headers to my windows server with two get parameters and a script there will execute and make a useracount for the new user. this works manualy and for 1 user just fine, however, i want to add cron to this so it runs every 15 minutes. this is'nt the problem when there is one user, but is the script has more then one user, it wont reach there becouse of the header. How can i fix this?
my code:
$array = $arr->invoices->invoice;
foreach($array as $key => $value) {
if(!order_is_active($value->id)) {
$username_win = strtolower($value->firstname) . rand(9,9999);
$password_win = ucfirst(maakpass(10, TRUE, TRUE));
if (add_user_to_db($value->id, $value->userid, $value->status, $username_win, $password_win)) {
header('location: http://ip/adduper/?username=' . htmlspecialchars($username_win) . '&password=' . htmlspecialchars($password_win));
} else {
echo 'order bestaat al';
}
}
}

You can store all of the users in an array and then send the json encoded string to your other server which will then json_decode it to get back an array. It can then loop over the array and add each user.

Rather than doing a header, I'd move toward doing CURL
This will allow you to more cleanly return from the Windows machine a status of success or failure. As with all remote connections, you have to account for when one machine can't connect to the other.....and it isn't a matter of if that case will happen, but when. Such is the nature of the Internet.
With a PHP header, a failed connection would create all sorts of chaos.

Related

php and mysqli actions in cron jobs?

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.

how to speed up a cakephp action that take a long time to finish by using threads

I have a controller method that takes a long time (40 minutes) to complete. the method retrieve 3500 domain name and for each one it should search registrar name, expire that and also check if http server is running or not. This is the reason it's taking so long;
this is my code, it works, but slow :
public function sync_domains(){
// get the domain name list
$list = $this->Domain->find('all');
// search for registrar name, expire date and web server status (up|down)
foreach ($list as $key => $record) {
$hostname = $record['Domain']['domain_name'];
$domain = array();
// get registrar name and expire date
$whois = $this->whois($hostname);
$domain['Domain']['registrar'] = $whois['registrar'];
$domain['Domain']['expire_date'] = $whois['expire_date'];
// get the web status
$domain['Domain']['web_status'] = $this->httpStatus($hostname);
$newData[] = $domain;
}
// save new data
if(!empty($newData)){
if($this->DomainStatus->saveMany($newData)){
$this->Flash->success(__(count($newData).' Domains has been added successfully'), array('key' => 'success'));
}else{
$this->Flash->danger(__('An Error occured while saving data'), array('key' => 'danger'));
}
}
// redirect to referer
return $this->redirect($this->referer());
}
is there any way to use multithreading to launch whois and httpstatus functions for multiple domain name at the same time ?
thanks,
If it's a one-off job, a common approach is to divide the database results in batches and manually execute them, either via command line or simply using your web browser and accessing each batch in a different tab (or on different browsers).
An example implementation:
public function sync_domains($batch){
$numberOfItemsPerBatch=500;
// get the domain name list
$list = $this->Domain->find('all',[
'limit'=>$numberOfItemsPerBatch,
'offset'=>$batch*$numberOfItemsPerBatch
]
);
//process data
You would then access the following URLs concurrently:
http://example.com/my_controller/sync_domains/0
http://example.com/my_controller/sync_domains/1
http://example.com/my_controller/sync_domains/2
etc...
This will reduce your processing time from 40 to 5-6 minutes. Make sure your max_execution_time is set to allow this.
If you try to use your browser, you will notice that you are not able to load a new view if a previous one is still being processed. This is due to PHP Session Locks. An easy workaround is to use Chrome Incognito Mode or Firefox's Private Browsing to access your site concurrently.
A simpler option is perhaps to just open a shell and run
$ wget http://example.com/my_controller/sync_domains/0 &
$ wget http://example.com/my_controller/sync_domains/1 &
$ wget http://example.com/my_controller/sync_domains/2 &
etc...

Prevent PHP from sending multiple emails when running parallel instances

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();

Maintaining counter value in PHP

I'm working on a system where an android app needs to send periodic updates to a server to say it is running okay. If 4 checks pass and an update hasn't been sent, a text message needs to be sent. I want to use a counter in the PHP file that checks how many 'checks' have passed without an update. However every time the android application contacts the server the counter is reset and never increases. I have it working but I don't want the message to be sent until the counter is 4. Does anyone have any suggestions on how to retain the value of the counter when the file is 'reopened'. Thanks.
<?php
//...
// check the value sent from the android application
if(isset($_REQUEST['alert'])){
echo "alert";
// everything is ok, reset the counter
$counter = 0;
}
else echo "no alert";
// increase the counter
$counter++;
if($counter >= 4) {
while($row = mysql_fetch_array($result)) {
$phNum = $row['mobile'];
}
// an update has not been sent in 4 attempts, send a text message
send_sms($phNum);
}
//...
?>
Perhaps you could:
Use SharedPreferences in Android App which would keep count of checks? then send it to server to say all 4 checks were passed?
PHP script is executed from beginning every time you visit website, another method would be to use sessions but that will get a bit messy, and another way: when request is called, it would send your data + device ID (unique ID to each device), then it would add number of checks into database and keep track of checks for each device, that would slow down your execution time by not that much.
But as I said already, Shared Preferences would work.
If your android app is properly sending and storing cookies you can use the php $_SESSION or $_CCOKIE variable for persistent data.

PHP: Most efficient way to make multiple fsockopen(); connections?

Hey guys i'm making a website where you submit a server for advertising. When the user goes to the index page of my website it grabs the ip's of all the servers submitted and then tests to see if it is online using fsockopen() like so:
while($row = mysql_fetch_assoc($rs)) {
$ip = $row['ip'];
$info = #fsockopen($ip, 25565, $errno, $errstr, 0.5);
if($info) {
$status = "<div><img width='32px' height='32px'
title='$name is online!' src='images/online.png'/></div>";
$online = true;
} else {
$status = "<div><img width='32px' height='32px'
title='$name is offline!' src='images/offline.png'/></div>";
$online = false;
}
}
}
This way works fine, but the only downside is when you load the site it takes a good 2-4 seconds to start loading the website due to the fsockopen() methods being called. I want to know if there is a better way to do this that will reduce the amount of wait time before the website loads.
Any information will be appreciated, thanks.
Store the online status and last check time in a database, if the last check time is longer than 15 minutes for example, update it. I am pretty sure you don't need to get the status on EVERY pageload? It's the time it takes to connect to each server that slows down the website.
Then again, you would probably wanna move the update process to a cronjob instead of relying on someone visiting your website to update the server statuses.
Looking at your example, I'd make all the $status bits be javascript calls to another php page that checks that individual server.
However, the idea to move the status checks to cron job or use some kind of status caching is very good too. Maybe store statuses in a database only only check the ones that have expired (time limit set by you).

Categories