put in simple words:
i am writing php scripts which send and receive sms,
scripts will calculate to send users campaign SMS every week based on each user registration date, for example every monday 10 AM send sms to mr. A and every friday at 7 pm sends sms to miss B..
and php scripts will take care of everything needed ..
problem : obviously a very funny way is to have someone refresh the main page of my application every some seconds or so to be able to continue to calculate and understand what and when to do jobs, or have the main page always open on my computer so javascripts and jquery will handle the rest!
My Question : how can i have my php program or scripts to be something like awake without need to someone refreshes or have open the main page? by awake i mean like it senses the next schadule and executes it and so on ..
some raw ideas to answer : perhaps i could call the main page using ajax or curl every 10 seconds .. but i don't know how to awake ajax or curl in first place ..
i see some internet posts suggest something like command line either in linux unix or windows .. but i usually access the host not the command line is it right ? or command line is something in host and i don't know it, if so please help me ..
important example : there are php wp plugins like total cache and supper cache which seem to be always on and awake of schedules without need of somebody refreshing a page ..
please give answers all in php and php families if possible, i don't know unix or those kind of programmings at all ..
------- accourding to answers made some progress to question ..
now i have this bellow script :
ignore_user_abort(true);
set_time_limit(0);
$data = file_get_contents('filename.txt');
$data = $data+1;
file_put_contents('filename.txt', $data);
$page = $_SERVER['PHP_SELF'];
$sec = "4";
header("Refresh: $sec; url=$page");
it works! even when i restart the local host . main problem is now when i closed the main page it stopped incrementing in filename.txt and when reoppend the page two instance where running the increment continued so :
should'nt it continue to increment even when i close the page ?
and how i stop it ?
and is it normal to have more than one instance of the page run in background?
finally : according to instructions on this page it's best i create a starter or reload page then use commands to initiate this reload page for example every 1 minute and then write PHPs like normal ..
last not least : how to stop this background script ? for update or maintenance ..
For this particular issue cron jobs have been invented. Cron jobs are timed jobs that can for example execute a PHP script.
You could set up a cron job to check which user should receive his/her sms every hour. Depending on your operating system you can set up these cron jobs. For linux distrubutions there are tons of guides on how to set this up.
From Wikipedia:
The software utility Cron is a time-based job scheduler in Unix-like computer operating systems. People who set up and maintain software environments use cron to schedule jobs (commands or shell scripts) to run periodically at fixed times, dates, or intervals. It typically automates system maintenance or administration—though its general-purpose nature makes it useful for things like downloading files from the Internet and downloading email at regular intervals. The origin of the name cron is from the Greek word for time, χρόνος (chronos). (Ken Thompson, author of cron, has confirmed this in a private communication with Brian Kernighan.)
I have added a resource explaining how to use cron jobs.
An alternative method is to keep a PHP script running in the background:
// Keep executing even if you close your browser
ignore_user_abort(true);
// Execute for an unlimited timespan
set_time_limit(0);
// Loop infinitely
// If you create a file called stop.txt,
// The script will stop executing
while (!file_exists('stop.txt')) {
// Retrieve user data and sens sms messages
// Wait for an hour
sleep(3600);
}
Update
ignore_user_abort(true);
set_time_limit(0);
$data = file_get_contents('filename.txt');
while (!file_exists('stop.txt')) {
// Add 1 to $data
$data = $data+1;
// Update file
file_put_contents('filename.txt', $data);
// Wait 4 seconds
sleep(4);
}
To stop executing create a file called stop.txt
Resources
About Cron jobs
You can create cron jobs in almost all servers without accessing command prompt.
Cron job can be used to initialize php scripts in cli at specified intervals lik every minute, every hour etc
Related
Trying to make a dice-roll function in my telegram bot.
How it works right now:
When a user sends "roll" bot replies with sendDice method and sends another message with result like "you rolled 5, you won and blah-blah .."
> how it looks <
The problem is — the second message should not appear instantly, ideally after dice-roll animation is finished.
My first and obvious try on that was to add "sleep(3)" before sending the second message, and it worked fine, until I realized it completely delays the execution of my script for those 3 seconds. (if two users rolled at the same time, one of the users has to wait until another guy's roll will be finished). So it's not cool
What can I use? :c
The easiest option is to add the "task" to the "queue". The queue can be a table in the database with timestamps and chat id, when and to whom to send a message. Start another process, for example, which is started by cron, and it works for one minute. During that minute, he goes to the database and checks to see if there is something that needs to be sent now.
Crontab config
Open crontab
sudo crontab -e
Add next string
* * * * * php /path/to/cron.php >> /path/to/log/file/for/debug.log 2>&1
Cron run your script every 1 minute.
Cron.php "live" 60 second
cron.php:
$now = time();
$expectedTime = $now + 60;
while (true) {
Worker::run();
if ($expectedTime < time()) {
die(0);
}
}
Where Worker::run() your method, which get records from db, check timestamp and send message
From Wikipedia:
In computing, [..] fork is an operation whereby a process creates a
copy of itself.
When your PHP script runs, you can create multiple processes that interact with each other. Those processes run concurrently and asynchronous. This way you can have one process waiting to send the message, while the rest of the script continues to run.
Instead of starting another process, you could also start another thread. The technical difference between the two is explained here:
Forking vs Threading
PHP offers Process Control Extensions for both forking and threading. You might want to check out the example in the PHP documentation for pcntl_fork().
Depending on your needs, you might want to use a framework designed to handle concurrency throughout your application. If that is the case, I would recommend amphp.
Here's what I'm trying to accomplish in high-level pseudocode:
query db for a list of names (~100)
for each name (using php) {
query a 3rd party site for xml based on the name
parse/trim the data received
update my db with this data
Wait 15 seconds (the 3rd party site has restrictions and I can only make 4 queries / minute)
}
So this was running fine. The whole script took ~25 minutes (99% of the time was spent waiting 15 seconds after every iteration). My web host then made a change so that scripts will timeout after 70 seconds (understandable). This completely breaks my script.
I assume I need to use cronjobs or command line to accomplish this. I only understand the basic us of cronjobs. Any high level advice on how to split up this work in a cronjob? I am not sure how a cronjob could parse through a dynamic list.
cron itself has no idea of your list and what is done already, but you can use two kinds of cron-jobs.
The first cron-job - that runs for example once a day - could add your 100 items to a job queue.
The second cron-job - that runs for example once every minute in a certain period - can check if there are items in the queue, execute one (or a few) and remove it from the queue.
Note that both cron-jobs are just triggers to start a php script in this case and you have two different scripts, one to set the queue and one to process part of a queue so almost everything is still done in php.
In short, there is not much that is different. Instead of executing the script via modphp or fcgi, you are going to execute it via command line php /path/to/script.php.
Because this is a different environment than http, some things obviously don't work. Sessions, cookies, get and post variables. Output gets send to stdout instead of the browser.
You can pass arguments to your script by using $argv.
This question already has answers here:
Schedule and execute a PHP script automatically
(7 answers)
Closed 9 years ago.
I am developing a web app which requires events. The user creates an event at a specific time, and I need a script to be executed and activate the event at the exact time, so the event can start.
Any ideas on how I can do this? I googled and searched through stack overflow, but all I encountered was multiple execution at specific time. What I need is execution at automatically set time.
Hope you help me, I'm desperate.
You have 3 options. My recommendation: Use cron if you can, user driven if you have to, and daemon as a last resort.
(1) cron (as mentioned in comments)
cron is a scheduler for linux systems that will run a command line job on your system. You log into your server over ssh, type crontab -e, and add a line like this:
4 5 * * * php /path/to/my/script.php
This would run the script at 5:04 a.m. every day.
<?php
// /path/to/my/script.php
// Do something
Some hosting services allow entering cron jobs with a GUI. There are also external cron services, that will call a URL for you at specific times.
(2) daemon
This is the most advanced option and also the least reliable: You run a command line script that contains an infinite loop. The script then periodically checks state and responds to it. Because it is likely to crash after months of running, you have to have a second script to restart it in case it does. This is a lot of work, but it is the most flexible approach.
<?php
while (1) {
// fetch $last_exec_timestamp from database
if ($last_exec_timestamp < time() + 86400) {
// set last_exec_timestamp to now in database
// do something
}
sleep(5);
}
3. user driven
If you have a decent amount of traffic on your site, you can simply include a the job this in your page footer, when there is no more output. Make sure this code is fast, or an unlucky user will be waiting for it.
<?php
// fetch $last_exec_timestamp from database
if ($last_exec_timestamp < time() + 86400) {
// set last_exec_timestamp to now in database
// do something
}
There are also to more fancy approaches of "user driven" that I haven't personally tested in another stack overflow question.
What u are looking for is CRON JOBS
http://net.tutsplus.com/tutorials/php/managing-cron-jobs-with-php-2/
Good day to all.
I need to do this:
From a computer somewhere in this world I need to access a specific URL and start a process. The only problem is that since the process may last over 5 hours and may return some errors (the process will move over them) PHP commands like exec, shell_exec, etc don't work (don't exactly know why but... all return error and stop execution)... so I tried this:
I made a cron that runs a script
use php to write the script file
Everything works fine but I need to return a counter telling me when the process will start so, when I run the php script that edit the shell script I return the hour of the system and start counting till the next full minute (when the script will be executed).
Now the only problem is this:
The counter SEEMS to work ok... but also the process needs some time to start and that time may vary from 3-4 sec to 1 minute. My question is... can I get sometime of hint at least if not the exact time of when the process will start up and the exact time when it did start?
I dunno... like writing in a file and a php script read it for a minute to see when something changed?
Ok... I promised I'll add some details:
The process is streaming. Live. So this is what I need to do:
create a stream
give a counter to the user when the stream will start
I use ffmpeg for streaming. The start.php have something like:
// Create a file called script.sh
$string = "ffserver & ffmpeg -i pipe.avi http://localhost:8090/feed1.ffm& echo exit 0 > script.sh& exit 0";
//write string to script.sh
//create a file that contains the exact time when the script was run.
The cron looks like this:
* * * * * /var/www/html/script.sh > /dev/null
and some other crons that doesn't matter
So I can create a counter that gets the time when the script was run and count till the next minute when the cron will run. The thing is that ffmpeg has some time until it starts (testing codecs, checking file etc.) I need to get that time and include it in timer so when the stream starts the guy that speaks says "Hello". Is not nice for him to do something like "Ok... is this working? Yes? Hello ppl." and is not good for the users to loose the first 3-4 sentences. That's why I need the moment when ffmpeg starts and somehow pass it to a php script. I can manage from there.
I have worked at places where crontab was only cycled every 5 mins, but more recently crontab seem to be cycled every 1 minute. It is probably a configurable value, so if you don't think your crontab is starting until some multiple of minutes that may be the reason.
Your process should start after the time seconds value moves from 59 to 00. There may also be minor delays starting the crontab entry if some other process is already using most/all of systems resources.
But looking at this from another point of view, if you are creating crontab entries with a specific time value, then you know what time to start looking at, + 2-3 seconds, right?
Please modify your posting to include a sample of what your crontab entry that your system creates looks like (are there any '*' in it, being my main interest).
Rereading your post, I see you're not programamtically creating the crontab entry. Nevermind on that.
If your process is running for many hours, why you need to immediately attach to it. If it crashes in the first 30 seconds, isn't waiting 1 minute max to find that out good enough?
Finally, in the shell environment, there is 99.99999% of the time, a way to capture a process's output from the very beginning. The idea of having to wait, to start getting the output requires more explanation. Is this something todo with that the program is running on a remote machine? The remote program should capture it's output, and then you 'get' that output as a seperate sub/co-process.
I hope this helps.
I'm pretty sure I've seen this done in a php script once, although I cant find the script. It was some script that would automatically check for updates to that script, and then replace itself if there was an update.
I don't actually need all that, I just want to be able to make my PHP script automatically run every 30 minutes to an hour, but I'd like to do it without cronjobs, if its possible.
Any suggestions? Or is it even possible?
EDIT: After reading through a possible duplicate that RC linked to, I'd like to clarify.
I'd like to do this completely without using resources outside of the PHP script. AKA no outside cronjobs that send a GET request. I'd also like to do it without keeping the script running constantly and sleeping for 30 minutes
If you get enough hits this will work...
Store a last update time somewhere(file, db, etc...). In a file that gets enough hits add a code that checks if the last update time was more xx minutes ago. If it was then run the script.
You may want to use the PHP's sleep function with specified time to run your code with that interval or you may want to try some online cron job services if you wish.
Without keeping the script running constantly, you'll either have to use something hackish that's not guaranteed to actually run (using regular user pages accesses to run a side routine to see if X amount of time has passed since last run of the script and if so, run it again), or use an external service like cron. There's no way for a regular PHP script to just magically invoke itself.
You can either use AJAX calls from your real visitors to run scheduled jobs in the background (google for "poor man's cron", there are a number of implementations out there) or use some external cron-like service (for example a cronjob on some other machine). In theory you could just run a PHP script with no timeout and make it loop forever and fire off requests at the appropriate time, but the only thing that would achieve is reinventing cron in a very ineffective and fragile way (if the script dies for some reason, it will never start again on its own, while cron would just call it again).
Either way, you will need to set proper execution time so the script does not exceed it.
I found this:
<?php
// name of your file
$myFile="time.db";
$time=file($myFile);
if(time()-3600 > $time[0]){
// an hour has elapsed
// do your thing.
// write the new timestamp to file
$fh = fopen($myFile, 'w') or die("can't open file");
fwrite($fh, time());
fclose($fh);
}
else{
// it hasn't been an hour yet, so do nothing
}
?>
in here
If the host includes a mysql 5.1+ db then perhaps timed triggers are availible to call the script? I like these mission impossible type questions, but need more information on what kind of playground and rules for the best answer.