Tagged: Linux

PHP: Better way to manage your cron rather than writing all in crontab

In PHP , if we are writing the scheduled tasks in core php,

then, we need to setup the individual cron in either crontab in linux or schedule task in windows.

Whenever there are number of crons in a product across multiple platform , it hard to setup all and manage
and one more thing, somehow managing cron is also outside of the code or developer scope in traditional way.

However, the following is not the best way to manage, but still a better way rather than scattered code.

Code : –

<?php
// list of crons
$crons = array(
// command line script
    array(
        "time" => '00 02 * * *',
        'execute' => '/usr/bin/php ' . '/var/www/html/test/cron.php > /dev/null'
    ),
// get url
    array(
        "time" => '*/5 * * * *',
        'execute' => 'wget -O - ' . 'https://developerck.com/test/cron.php'
    )

);

if (empty($_GET['web'])) {
    runcron($crons);
} else {
    printcrons($crons);
}

/*
 * functions to print and run crons
 *
 * if you want to print the list of crons
 * printcrons($crons)
 *
 * runcron($crons) will trye to execute all setup crons
 *
 * (With the above code , you can pass query parameter web to true , ?web=1 to print)
 *
 */

// Printing Crons
function printcrons($crons)
{
    $str = "<table>";
    foreach ($crons as $e) {
        $str .= "<tr>";
        $str .= "<td>" . implode(" ", $e) . "</td>";
        $str .= "</tr>";
    }
    $str .= "</table>";
    echo $str;
}

// function to run crons
function runcron($crons)
{
    // check if shell_exec function is allowd or disabled
    if (function_exists('shell_exec')) {
        foreach ($crons as $c) {
            $time = time();
            // check if it is the time to execute
            if (is_time_cron($time, $c['time'])) {
                // if you wnat to print the command
                echo $command = $c['execute'];
                $str = PHP_EOL . "||" . date("Y-m-d H:i:s") . "||" . $command . PHP_EOL;
                // log all the things under cron.txt
                @file_put_contents("cron.txt", $str, FILE_APPEND);
                // // execute commands
                @shell_exec($command);
            }
        }
    } else {
        echo "shell_exec function does not exist or disabled";
    }
}

// function to check if it is the time to run the cron
function is_time_cron($time, $cron)
{
    $cron_parts = explode(' ', $cron);
    if (count($cron_parts) != 5) {
        // checking for * * * * *
        return false;
    }
    
    $c = explode(' ', $cron);
    $min = $c[0];
    $hour = $c[1];
    $day = $c[2];
    $mon = $c[3];
    $week = $c[4];
    $to_check = array(
        'min' => 'i',
        'hour' => 'G',
        'day' => 'j',
        'mon' => 'n',
        'week' => 'w'
    );
    
    $ranges = array(
        'min' => '0-59',
        'hour' => '0-23',
        'day' => '1-31',
        'mon' => '1-12',
        'week' => '0-6'
    );
    
    foreach ($to_check as $part => $c) {
        $val = $$part;
        $values = array();
        
        /*
         * For patters like 0-23/2
         */
        if (strpos($val, '/') !== false) {
            // Get the range and step
            list ($range, $steps) = explode('/', $val);
            
            // Now get the start and stop
            if ($range == '*') {
                $range = $ranges[$part];
            }
            list ($start, $stop) = explode('-', $range);
            
            for ($i = $start; $i <= $stop; $i = $i + $steps) {
                $values[] = $i;
            }
        } /*
           * For patters like :
           * 2
           * 2,5,8
           * 2-23
           */
        else {
            $k = explode(',', $val);
            
            foreach ($k as $v) {
                if (strpos($v, '-') !== false) {
                    list ($start, $stop) = explode('-', $v);
                    
                    for ($i = $start; $i <= $stop; $i ++) {
                        $values[] = $i;
                    }
                } else {
                    $values[] = $v;
                }
            }
        }
        
        if (! in_array(date($c, $time), $values) and (strval($val) != '*')) {
            return false;
        }
    }
    
    return true;
}

The above code has three functions .

  • is_time_cron () : check whether it is time to run the cron or not
  • printcrons() : if you just want to print the scheduled crons
  • runcron() : you can pass the array of the cron. this function is only needed to call and and it will internally call is_time_cron.
 array("time" => '00 02 * * *',
 'execute' => '/usr/bin/php ' . '/var/www/html/test/cron.php > /dev/null')

Time is the scheduled time at which the cron will run and execute contains the command which needs to be run.

the following https://crontab.guru/ will help you understand the logic behind time ‘ * * * * *’

All in one .htaccess For the wordpress

All in one .htaccess file for the wordpress,

which is utilised for the security restrictions and caching management for the apache webserver.

  • Compressing the static files
  • setting up the cache headers for optimisation
  • Disable Image hotlinking for security
  • Removing directory Browsing fore security

# TN START GZIP COMPRESSION
<IfModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE “application/atom+xml” \
“application/javascript” \
“application/json” \
“application/ld+json” \
“application/manifest+json” \
“application/rdf+xml” \
“application/rss+xml” \
“application/schema+json” \
“application/vnd.geo+json” \
“application/vnd.ms-fontobject” \
“application/x-font” \
“application/x-font-opentype” \
“application/x-font-otf” \
“application/x-font-truetype” \
“application/x-font-ttf” \
“application/x-javascript” \
“application/x-web-app-manifest+json” \
“application/xhtml+xml” \
“application/xml” \
“font/eot” \
“font/otf” \
“font/ttf” \
“font/opentype” \
“image/bmp” \
“image/svg+xml” \
“image/vnd.microsoft.icon” \
“image/x-icon” \
“text/cache-manifest” \
“text/css” \
“text/html” \
“text/javascript” \
“text/plain” \
“text/vcard” \
“text/vnd.rim.location.xloc” \
“text/vtt” \
“text/x-component” \
“text/x-cross-domain-policy” \
“text/xml”
</IfModule>
# TN – START EXPIRES CACHING
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css “access 1 month”
ExpiresByType text/html “access 1 month”
ExpiresByType image/gif “access 1 year”
ExpiresByType image/png “access 1 year”
ExpiresByType image/jpg “access 1 year”
ExpiresByType image/jpeg “access 1 year”
ExpiresByType image/x-icon “access 1 year”
ExpiresByType image/svg+xml “access plus 1 month”
ExpiresByType audio/ogg “access plus 1 year”
ExpiresByType video/mp4 “access plus 1 year”
ExpiresByType video/ogg “access plus 1 year”
ExpiresByType video/webm “access plus 1 year”
ExpiresByType application/atom+xml “access plus 1 hour”
ExpiresByType application/rss+xml “access plus 1 hour”
ExpiresByType application/pdf “access 1 month”
ExpiresByType application/javascript “access 1 month”
ExpiresByType text/x-javascript “access 1 month”
ExpiresByType text/x-component “access plus 1 month”
ExpiresByType application/x-shockwave-flash “access 1 month”
ExpiresByType font/opentype “access plus 1 month”
ExpiresByType application/vnd.ms-fontobject “access plus 1 month”
ExpiresByType application/x-font-ttf “access plus 1 month”
ExpiresByType application/font-woff “access plus 1 month”
ExpiresByType application/font-woff2 “access plus 1 month”
ExpiresDefault “access 1 month”
</IfModule>
# TN – BEGIN Cache-Control Headers
<ifModule mod_headers.c>
<filesMatch “\.(ico|jpe?g|png|gif|swf)$”>
Header set Cache-Control “public”
</filesMatch>
<filesMatch “\.(css)$”>
Header set Cache-Control “public”
</filesMatch>
<filesMatch “\.(js)$”>
Header set Cache-Control “private”
</filesMatch>
<filesMatch “\.(x?html?|php)$”>
Header set Cache-Control “private, must-revalidate”
</filesMatch>
</ifModule>

# TN – DISABLE IMAGE HOTLINKIING START
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?<example.com> [NC] # please replace <example.com> with your domain like abc.com or any
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?google.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ – [NC,F,L]
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]
</IfModule>
# Redirecting to index
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ – [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# Deny XMLRPC
<files xmlrpc.php>
order allow,deny
deny from all
</files>

# disable directory browsing
Options All -Indexes
<files wp-config.php>
order allow,deny
deny from all
</files>
# TN – DISABLE IMAGE HOTLINKIING END
<IfModule pagespeed_module>
ModPagespeed on
ModPagespeedEnableFilters rewrite_css,combine_css
ModPagespeedEnableFilters recompress_images
ModPagespeedEnableFilters convert_png_to_jpeg,convert_jpeg_to_webp
ModPagespeedEnableFilters collapse_whitespace,remove_comments
</IfModule>