I've seen some similar questions at SO but none of then have answered me. I had never heard of CRON before and I'm new to Laravel. What I need is to run a Task once a week to perform some actions on my database (MySql), say every sunday at 12:00 am. How could I achieve this goal?
If you can use cron, you just have to execute
crontab -e
Or, if you need to run as root:
sudo crontab -e
This will open a text editor so you can modify your crontab and there you'll have one line for each scheduled command, as this one:
1 0 * * * php /var/www/myBlog/artisan task:run
The command in this like will be executed at the first minute of every day (0h01 or 12h01am).
Here is the explanation of it all:
* * * * * <command to execute>
┬ ┬ ┬ ┬ ┬
│ │ │ │ │
│ │ │ │ │
│ │ │ │ └───── day of week (0 - 6) (0 to 6 are Sunday to Saturday, or use names)
│ │ │ └────────── month (1 - 12)
│ │ └─────────────── day of month (1 - 31)
│ └──────────────────── hour (0 - 23)
└───────────────────────── min (0 - 59)
So, in your case, you'll create a line like this:
0 12 * * 0 <command to execute>
But how do you do that for a task in Laravel? There are many ways, one of them is in my first example: create an artisan command (task:run) and then just run artisan, or you can just create a route in your app to that will call your task every time it is hit:
Route::get('/task/run',array('uses'=>'TaskController#run'));
And then you just have to add it your crontab, but you'll need something to hit your url, like wget or curl:
0 12 * * 0 curl http://mysite.com/run/task
Since Laravel 5, the only entry you need to put into crontab after executing crontab -e is
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
Do remember to change /path/to/artisan part to your project specific path.
And then you can define your scheduled tasks and running frequency in Laravel's App\Console\Kernel class. See Laravel documentation for more information: Task Schedule
You can create and run your laravel tasks from the command line just like any other Artisan command. So if you are on windows you can just run the command manually to see if it works or not.
Then when you are on production server (better of course if it is Unix based) then you can follow Antonio's direction to create the cron job and add it to the cron tab. Keep in mind you will need to know the complete paths for the PHP execution.
My tutorial explains this all in detail : http://maxoffsky.com/code-blog/practical-laravel-using-cron-jobs-in-laravel/
Hope you find the answer that you are looking for.
Related
I have configured cron job but it's not working.
I wanted to run the myfile.sh script for every 2 mint and below are my configuration in crontab.
# m h dom mon dow comman
2 * * * * /home/ubuntu/myfile.sh
myfile.sh is executable and contains below lines of code
#!/bin/bash
mysqldump -u[user] -p[password] --single-transaction --routines --triggers --all-databases > /home/ubuntu/backup_db10.sql
Is there anywhere we need to add configure anything?
You're running the script at two minutes past every hour. As in 1:02, 2:02 and so on.
You can change it to something like
*/2 * * * * /home/ubuntu/myfile.sh
to run it every two minutes.
A bit more info can be found here.
I have a node script that I want to run periodically so I created the following Dockerfile to run it from a cron task:
FROM node:8
RUN apt-get update && apt-get install -y cron
# ensure the node packages are installed in the image
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
# copy the node task to working directory
COPY db-update.js .
# copy the script which will start cron to the working directory
COPY startcron.sh .
# copy the cron task to the cond.d directory
COPY crontask /etc/cron.d/crontask
# give execution rights on the cron job and script
RUN chmod 0644 /etc/cron.d/crontask && chmod 777 ./startcron.sh
# apply the cron job
RUN crontab /etc/cron.d/crontask
# create the log file to be able to run tail
RUN touch /var/log/cron.log
# execute the command in the foreground
CMD /usr/src/app/startcron.sh
In startcron.sh bash script I have the following:
#!/bin/bash
set -e
printenv | sed 's/^\(.*\)$/export \1/g' > /tmp/env.sh
echo 'Starting cron' # <- ONLY THIS APPEARS IN MY CONTAINER LOGS
cron -f
I needed to create /tmp/env.sh to export the environmental variables my node script requires. This script should then start cron in the foreground. My crontask should "source" those environmental variables and run my node script. If I have set up everything correctly I expect to see the output from my node script in the logs of my Docker container.
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │ 7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * * command to execute
# DOES THIS COMMAND EXECUTE SUCCESSFULLY, IF NOT WHY NOT?
*/5 * * * * . /tmp/env.sh /usr/local/bin/node /usr/src/app/db-update.js > /proc/1/fd/1 2>/proc/1/fd/2
# need to leave an empty line
This is a snippet from my node script:
const sftpclient = require('ssh2-sftp-client');
const expressGraphQL = require('express-graphql');
const mongoose = require('mongoose');
const fs = require('fs');
console.log('now executing db-update');
const IN_PRODUCTION = (process.env.NODE_ENV === 'production' ? true : false);
console.log('what is node env: ', process.env.NODE_ENV);
console.log('what is env: ', process.env);
When I run this container, however, the only output I am seeing in my container logs is the echo command from my bash script "Starting Cron". I don't see any output from the node script but the container continues to run. How can I ensure that the node script runs or that the container fails if it doesn't?
To make your life much more easier I would recommend to change strategy to use simple infinite loop with sleep instead of cron
so in CMD just place
while true; sleep 300; execute-node-program || exit 1; done
In such strategy:
You have all output of your node program in docker logs
Container will fail if your program fail
It will be hard to achieve that by using cron as you will need probably to place systemd for 2 processes:
One process for cron
Second process to observe what is node program output and kill systemd if needed, print logs, etc. <--- that sounds really bad
Edit:
So to give you idea how to deal with killing your container when cron job fails:
Start your container with --init flag e.g. docker run --init... - that's really important and will allow you to kill main container's process from within container
Use similar crontab record: */5 * * * * bash -c "/tmp/env.sh && /usr/local/bin/node /usr/src/app/db-update.js || pkill -9 -f cron" > /proc/1/fd/1 2>/proc/1/fd/2
I have an TP Link Archer C7 with 15.05 Chaos Calmer at home.
I am trying to get the cronjob to work. It looks like this:
* * * * * /usr/bin/wget --spider \"https://subdomain.domain.net/update.php\" >/dev/null 2>&1
Unfortunately this does not get executed. I also tried to do* * * * wget -O - https://subdomain.domain.net/update.php same result.
BOTH versions are executed correctly if entered through the console directly.
Last line of logread
Tue Sep 20 11:55:00 2016 cron.info crond[10317]: USER xxx pid 16697 cmd /usr/bin/wget --spider \"https://subdomain.domain.net/update.php\" >/dev/null 2>&1
Looks correct? Any idea why it is not executed through the cronjob?
Your cron job does run, but wget runs into an error.
Also to get a log, i.s.o. redirecting to /dev/null, you cannot use /out.txt, as cron will have no write access to /, /tmp/wget.txt will do fine.
Same goes for the wget command, where does the output get stored? you should use use -p <directory prefix> option.
Secondly you need to handle if data is already in that directory, which could be to use -N and only download newer files and override the old ones.
Thirdly use the -q option when all is working to quiet down wget output.
Fourthly you cannot run the script every minute * * * * *, as previous run might not have finished yet, see format:
# ┌───────────── min (0 - 59)
# │ ┌────────────── hour (0 - 23)
# │ │ ┌─────────────── day of month (1 - 31)
# │ │ │ ┌──────────────── month (1 - 12)
# │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to
# │ │ │ │ │ Saturday, or use names; 7 is also Sunday)
# │ │ │ │ │
# │ │ │ │ │
# * * * * * command to execute
For the sake of test let's run it every night at 1 past midnight.
Remark: To really make it correct, you should use a script file to execute and put wget command in there, where as the script file could make a lock in case you want to execute this frequently, see here for advice as this is beyond the scope of this question/answer.
And Number 5: don't need to escape the " with \", even so the " is not needed, so remove it.
In conclusion, make first a directory where data can be stored e.g. /wget_data
mkdir /wget_data
chmod 777 /wget_data
then adjust your cron line, add the -p <directory prefix> and -N and adjust the execute format:
1 0 * * * /usr/bin/wget -N -p /wget_data --spider https://subdomain.domain.net/update.php >/tmp/wget.txt 2>&1
and restart your cron, can't advice on that, don't known what is used yet.
also wise would be to to test your command from the command line first with:
/usr/bin/wget -N -p /wget_data --spider https://subdomain.domain.net/update.php >/tmp/wget.txt 2>&1
and then cat /tmp/wget.txt to see if the command worked, and ls /wget_data to see if wget did collect data.
Main things you need to check:
If crond is up and running ( top , ps -A )
If crond has enough permissions to execute wget ( ls -l /usr/bin )
If wget does not produce any errors (don't throw away output to /dev/null, store it in some file and then check firstly - if file created at all, if not - tripple check things 1 and 2, if file is created and there is some information - it could be helpful)
Related to items 1 and 2. Check what user running crond and try to execute command using this user.
Try execute not wget but some command that will write some string to some file and check if it will works.
How do I configure my Vagrant configuration so that when I provision a machine its crontab is automatically configured? (vagrant is provisioned according to Chef(?) files)
As an example, I wanted to have the following cron set up:
5 * * * * curl http://www.google.com
Basic provisioning for things like this can easily be done without Chef/Puppet/Ansible and instead using the shell.
The Vagrant docs cover this basic provisioning pretty well for their example of having the box download Apache from a boostrap.sh.
Similarly you could follow the same steps in editing your Vagrantfile to call a bootstrap.sh file when being provisioned:
Vagrant.configure("2") do |config|
...
config.vm.provision :shell, path: "bootstrap.sh"
...
end
You could then create a bootstrap.sh file in the same directory as your Vagrantfile which would contain something like:
#!/bin/bash
# Adds a crontab entry to curl google.com every hour on the 5th minute
# Cron expression
cron="5 * * * * curl http://www.google.com"
# │ │ │ │ │
# │ │ │ │ │
# │ │ │ │ └───── day of week (0 - 6) (0 to 6 are Sunday to Saturday, or use names; 7 is Sunday, the same as 0)
# │ │ │ └────────── month (1 - 12)
# │ │ └─────────────── day of month (1 - 31)
# │ └──────────────────── hour (0 - 23)
# └───────────────────────── min (0 - 59)
# Escape all the asterisks so we can grep for it
cron_escaped=$(echo "$cron" | sed s/\*/\\\\*/g)
# Check if cron job already in crontab
crontab -l | grep "${cron_escaped}"
if [[ $? -eq 0 ]] ;
then
echo "Crontab already exists. Exiting..."
exit
else
# Write out current crontab into temp file
crontab -l > mycron
# Append new cron into cron file
echo "$cron" >> mycron
# Install new cron file
crontab mycron
# Remove temp file
rm mycron
fi
By default Vagrant provisioners run as root so this will append a cron job to the root user's crontab assuming it doesn't already exist. If you want to add it to the vagrant user's crontab then you will need to run the provisioner with the privileged flag set to false:
config.vm.provision :shell, path: "bootstrap.sh", privileged: false
How to configure a cron job to run every night at 2:30? I know how to make it run at 2, but not 2:30.
crontab -e
add:
30 2 * * * /your/command
To edit:
crontab -e
Add this command line:
30 2 * * * /your/command
Crontab Format:
MIN HOUR DOM MON DOW CMD
Format Meanings and Allowed Value:
MIN Minute field 0 to 59
HOUR Hour field 0 to 23
DOM Day of Month 1-31
MON Month field 1-12
DOW Day Of Week 0-6
CMD Command Any command to be executed.
Restart cron with latest data:
service crond restart
As seen in the other answers, the syntax to use is:
30 2 * * * /your/command
# ^ ^
# | hour
# minute
Following the crontab standard format:
+---------------- minute (0 - 59)
| +------------- hour (0 - 23)
| | +---------- day of month (1 - 31)
| | | +------- month (1 - 12)
| | | | +---- day of week (0 - 6) (Sunday=0 or 7)
| | | | |
* * * * * command to be executed
It is also useful to use crontab.guru to check crontab expressions.
The expressions are added into crontab using crontab -e. Once you are done, save and exit (if you are using vi, typing :x does it). The good think of using this tool is that if you write an invalid command you are likely to get a message prompt on the form:
$ crontab -e
crontab: installing new crontab
"/tmp/crontab.tNt1NL/crontab":7: bad minute
errors in crontab file, can't install.
Do you want to retry the same edit? (y/n)
If you have further problems with crontab not running you can check Debugging crontab or Why is crontab not executing my PHP script?.
An easy way to write cron is to use the online cron generator
It will generate the line for you. One thing to note is that if you wish to run it each day (not just weekdays) you need to highlight all the days.
As an addition to the all above mentioned great answers, check the https://crontab.guru/ - a useful online resource for checking your crontab syntax.
What you get is human readable representation of what you have specified.
See the examples below:
30 2 * * * (answer of this question)
#daily
59 23 31 12 *
30 2 * * * wget https://www.yoursite.com/your_function_name
The first part is for setting cron job and the next part to call your function.
30 2 * * * Every Day at 2:30 Am
30-31 2 * * * Every Day at 2:30 -31 am
Along with he answers its important to understand the cron expressions , i face a lot of difficulty in understanding .
But an intuitive way to understand is given here .