Categories: PHP
Published 2020-06-10 18:40
Configuring CRON on a hosting server is usually an easy task, but sometimes it can be troublesome. It depends on possibilities shared by our hosting provider. In this tutorial I will present 4 ways to configure CRON tasks in different circumstances.
In this tutorial I will present all possible ways to automatic execution of CRON. I will show 3 ways allowed by hosting providers and one alternative solution. I assume that you already have your job scheduler and tasks ready to execute.
Environment presented in this article is Laravel in version 5.8. It allows fast and intuitive configuration of scheduler, which can be executed with one line in a shell. The tutorial will be especially helpful for people using this framework, cause I share solutions for problems that I was need to solve by myself. However every scheduler will be able to run the same way.
Many hosting providers have a PHP "proc_open" function disabled for security reasons and this function is required by Kernel class! If you're getting error "The Process class relies on proc_open, which is not available on your PHP installation.", read my post in which I show how to make custom scheduler for created CRON tasks and use it in practice.
Hosting services max. 3 ways of CRON configuration:
Independently from a way we will choose, in the configuration we need to set an interval to 1 minute. It is symbolized by a notation " * * * * * ", which means every minute, hour, day, month and day of a week. Example setup on a hosting panel:
Time to choose the way of execution.
In this traditional way we just need to enter a path to the file with executing scheduler. In case of Laravel, if we want to use the method of Artisan class, there will be issues related to missing namespaces in our raw PHP file. In order to run Laravel we need to include "autoload.php" file from "vendor" directory and put a path to the Artisan manually, cause aliases defined in "config/app.php" don't have an influence in this place.
// File "/server/cron.php"
require_once __DIR__ .'/../vendor/autoload.php';
use Illuminate\Support\Facades\Artisan;
$app = require __DIR__ .'/../bootstrap/app.php';
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
Artisan::call('schedule:run');
Defining a command to execute by the server is the easiest and the fastest way, if we have such command in our project. This command executes whole mechanism and run CRON schedule. In case of Laravel this is "artisan schedule:run" command. We can define such SSH command by ourselves as long as it's not triumph of form over usability.
php /path-to-project/artisan schedule:run >> /dev/null 2>&1
We start this command with "php" command, which will run a script of a file (in our case it's "artisan"). We need to remeber about specifying the PHP version, if default one is too low. Depend on our server, it may be necessary to change the prefix to "php-cli". The ending ">> /dev/null 2>&1" is a little bit specific command which, in simplification, mutes any responses of our code (including errors).
If for some reasons the above methods are not working and we want to use it at all costs, we can try to execute a PHP file, which will run a shell script. It is possible with functions "exec" and "shell_exec", however they are often disabled by hosting providers for security reasons. But you can try! In case of Laravel all you need to do is set a path to PHP file with the line below:
shell_exec("php73 artisan schedule:run");
If these functions are disabled for security reasons, you will get error "proc_open() has been disabled for security reasons". In this case, if the first way not working, we should make own scheduler and execute it by executing a file.
Interesting alternative, when we don't have a possiblity of shell command execution and we can't manage with configuration in case of file executing (but I hope you can after this tutorial). In this way just create new controller for CRON scheduler and run the Artisan method inside it like in the first point - with no worries that we must include missing files. The disadvantage is the fact that if we can't set a HTTP authorization, our script could be run by unauthorized persons, which in extreme cases (i.e. at a right time) can result in e.g. multiple sending of mails to our newsletter members. If we have such possibility, we can ask our hosting provider for a list of IPs used by a server and let for script exection only for trusted IPs.
Example solution for Laravel:
web.php
Route::group(['prefix' => 'cron'], function(){
Route::get('/execute', 'admin\CronController@execute')->name('admin.cron.execute');
});
App\Http\Controllers\admin\CronController.php
namespace App\Http\Controllers\admin;
use App\Http\Controllers\Controller;
use App\Guards\CronIPChecker;
class CronController extends Controller{
public function __construct(){
CronIPChecker::abortIfNotTrustedIP();
}
public function execute(){
\Artisan::call('schedule:run');
return response('Complete', 200);
}
}
App\Guards\CronIPChecker.php
We need to be sure that CRON will be executed only by our server or perchance by ourselves. Constact "LocalIP" has been defined for tests. For clarity and perchance enlargement in future we're creating seperate class "HostingProvider" from where we will get a list of verified IPs.
namespace App\Guards;
use App\Entities\HostingProvider;
class CronIPChecker{
const LocalIP = '127.0.0.1';
public static function abortIfNotTrustedIP(){
$allowedIPs = HostingProvider::getIPs();
$currentIP = $_SERVER['REMOTE_ADDR'];
if( !in_array($currentIP, $allowedIPs) )
abort(403, 'Access forbidden.');
}
}
App\Entities\HostingProvider.php
namespace App\Entities;
class HostingProvider{
public static function getIPs(){
return config('hosting.IPs');
}
}
Even if our hosting provider doesn't allow CRON configuration, it doesn't mean that we don't have such possibility at all.
Fortunately in the web we can find many tools used to executing CRON tasks. Of course they require URL link for this, so there will be a need of making the point 3. After preliminary analysis I could recommend website cron-job.org, which is completely free (though it requires making an account like probably everyone). Its undoubted benefit is possibility of HTTP authentication, so we don't need to secure a script, just use a protection in a .htaccess file - there is a link showing how to require login and password only for specific URL.
This is how example configuration looks like on cron-job.org:
As you can see, a job-scheduler is the basis, a rest is a way in which we will execute it. I presented all possibilites which we can find on our hosting and one alternative solution. Share your opinion if this tutorial was helpful, every remark is very important.
Maybe you know yet another way of CRON executing?
Join newsletter and decide what content you want to receive.