WordPress Regenerate Thumbnails Cronjob

I run a small alt new publishing website called HamburgersNHeroin.com - One of the tough things about running a site that has multiple different writers is how to enforce strict guidelines on correct image sizes to upload. Not being one for enforcing much on the site other than moderating I have decided to do what I do best.. Be lazy!

By lazy I mean writing a nice little PHP cron script that will execute every night at 1am and will resize/regenerate all my images in the uploads directory according to the image sizes I specified in the functions file of the theme I built for the site. So where the hell do I start, I like to think I have expert level knowledge of WordPress at this stage especially its database schema which I have learned inside out but I still had no idea how it went about generating its image thumbnails until I took over a project over year ago when I first started freelancing. The project was to post an old ASP website over to wordpress including all of its legacy posts and so my affair with learning the WP data schema was born, more so out of necessity and having to pay that months rent 🙂

So my first stop was to figure out how does WordPress and all of these plugins regenerate the thumbnails, the obvious place to start was to download all of those plugins and see how they work and supprisingly most of those plugins looks as though they have all ripped each other off, two of the most popular ones have almost exactly the same source code as each other with just variable names changed. Regardless what I managed to gather was that they all work off the same WP native function wp_generate_attachment_metadata() so with that part solved it wasnt too hard to pull out the full function necessary in all those plugins and edit it to make it more optimized and run through ONLY the images uploaded within the past 2 days - with that being said before you install this script as a cronjob it is advisable that you do one last Thumbnail Regeneration with one of the ajax plugins as it will cause less stress on your server than using this script to run through every image. So without further adieu. SSH into you VPS or Dedicated stack then switch to the root user account and navigate to your themes directory and create a new file with Vim (or just FTP in and create one that way its all the same) with an odd name like skxvnvhthz2k4w.php the odder and longer the better.

sudo -s

Then create the file

vim skxvnvhthz2k4w.php 
OR
nano skxvnvhthz2k4w.php
OR
touch skxvnvhthz2k4w.php

Change the files permissions so that only the root user may read, write and execute it

chmod u+rwx  skxvnvhthz2k4w.php

Once your script is created open it up and paste in the following

<? 

require('/var/www/yourwebsitesroot/wp-blog-header.php');
//require ( ABSPATH . 'wp-admin/includes/image.php' );

	global $wpdb;

    // select all images that are uploaded within the past 2 days - Could easily be set for 1 day but this works for me
    $images = $wpdb->get_results( "SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'image/%' AND DATE(`post_date`) > DATE_SUB(CURDATE(), INTERVAL 2 DAY)" );

    foreach ( $images as $image ) {
        
      $fullsizepath = get_attached_file( $image->ID );

      wp_update_attachment_metadata( $image->ID, wp_generate_attachment_metadata( $image->ID, $fullsizepath ) );

    }

So whats going on in here well the first require is necessary to pull in access to all of wordpress native functions - the commented out lined below is what those plugins would use because they are already a part of WordPress and not external so if you wanted to create your own WordPress regenerate plugin you would comment out the first line and just use this one.

Next up we have a lovely SQL statement, again similar to what you get in those plugins but I have optimized the query to only search for images that were created within the past 2 days, I find 2 days to be better than one in case your server goes down the night before for any reason and to be honest adding an extra day in there doesnt create much more overhead, at least for my website anyway.

Finally we have a nice foreach loop that loops through all those ID's that were uploaded with the past 2 days and in turn grabs their full file path and then passes them to a double whammy function that will generate the new image file sizes whilst also updating the databases wp_post_meta table with the new image sizes and how to associate them with the various posts.

Phew.... so now that we have that setup why not run a test on the commandline

php  /var/www/yourwebsitesroot/wp-content/themes/YOURTHEME/skxvnvhthz2k4w.php

Next up navigate to your latest uploads folder and sort the files by date so that todays files will be visible and check the timestamps of your files uplaoded within the past 2 days and you should see them updated - For testing this I usually add a new images size into the functions file like add_image_size( 'test', 125, 125, true ); and look for it in the list.

So now for the fun part - Automating a pain in the arse.

On your terminal locate the PHP binaries, to do that its pretty easy just fire off

which php

and it will probably tell you that your PHP binaries are located at /usr/bin/php so with that information now open up a new cronjob by executing

crontab -e

Next up paste in your cronjob - this one is set to go off every night at 130 and under it there is a test one commented out that will run every minute, to use the test one just check your
uploads folder for changes every minute and if you see new timestamps then comment it back out and use the main one again. Also worth noting is that we use the direct path to the PHP binary on your server, in my experience this is far more reliable when executing PHP scripts than just using 'php' on the terminat, the -q flag stops the execution from sending http headers

# This cronjob is set to run at 130am every single night
30 1 * * * /usr/bin/php -q /var/www/yourwebsitesroot/wp-content/themes/YOURTHEME/skxvnvhthz2k4w.php
# This is a commented out cronjob to run every single minute - do not use this except to test that your server is executing the cron
# */1 * * * *  /usr/bin/php -q  /var/www/yourwebsitesroot/wp-content/themes/YOURTHEME/skxvnvhthz2k4w.php

So thats it, you will never have to regenerate thumbnails every again unless you add a new image size and have to regenerate all the images in the uploads directory again.

For HamburgersNHeroin I have written a lot of scripts I might cover how to optimize all the images in your website every night also using a cronjob but with native linux libs rather than a php script, great for keeping your sites loading times low and all done while you sleep.

Comments

comments