Archive for the ‘Wordpress’ Category

WordPress Security: Fix WordPress wp-config.php improper permissions to protect your sites from Database password steal / Website deface

Thursday, March 12th, 2015

wordpress-security-Fix-wordpress-wp-config-improper-permissions-to-protect-your-sites-from-Database-pass-steal
Keeping WordPress Site / Blog and related installed plugins up-to-date
is essential to prevent an attacker to hack into your Site / Database and deface your site, however if you're a company providing shell access from Cpanel / Plesk / Kloxo Panel to customers often customers are messing up permissions leaving important security credential files such as wp-config.php (which is storing user / pass credentials about connection to MySQL / PostgreSQL to have improper permissions and be world readable e.g. have permissions such as 666 or 777 while in reality the WordPress recommended permissions for wp-config.php is 600. I will skip here to explain in details difference between file permissions on Linux as this is already well described in any Linux book, however I just will recommend for any Share hosting Admin where Wordperss is hosted on Lighttpd / Apache Webserver + Some kind of backend database to be extra cautious.

Hence it is very useful to list all your WordPress sites on server wp-config.php permissions with find like this:

 

find /  -iname 'wp-config.php' -print1;

 

I find it a generally good practice to also automatically set all wp-config.php permissions to 600 (6= Read / Write  permissions only for File Owner  user 0 = No permissions for All groups, 0 = No Permissions for all non-owner users)

If find command output gives you some file permissions such as:
 

ls -al /var/www/wordpress-bak/wp-config.php
-rw-rw-rw- 1 www-data www-data 2654 jul 28  2009 wp-config.php

 

E.g. file permission has 666 permissions (Readable for all users), then it is wise to fix this with:
 

chmod 600 /var/www/wordpress-bak/wp-config.php


It is generally a very good practice to run also a chmod 600 to each and every found wp-config.php file on server:
 

find /  -iname 'wp-config.php' -print1 -exec chmod 600 '{}' \;


Above command will also print each file to whcih permission is set to Read / Write for Owner (this si done with -print1 option).

It is a good practice for shared hosting server to always configure a root cronjob to run above find chmod command at least once daily (whenever server hosts 50 – 100 wordpress+ more sites).
 

crontab -u root -l | { cat; echo “05 03 * * * find /  -iname 'wp-config.php' -print1 -exec chmod 600 '{}' \; } | crontab – 


If you don't have the 600 permissions set for all wp-config.php files this security "backdoor" can be used by any existing non-root user to be read and to break up (crack)  in your database and even when there are Deface bot-nets involved to deface all your hosted server wordpress sites.

One of my servers with wordpress has just recently suffered with this little but very important security hole due to a WordPress site directory backup  with improper permissions which allowed anyone to enter MySQL database, so I guess there are plenty of servers with this hidden vulnerability silently living.

Many thanks to my dear friend (Dimitar PaskalevNomen for sharing with me about this vulnerability! Very important note to make here is admins who are using some security enhancement modules such as SuPHP (which makes Apache webserver to run Separate Website instances with different user), should be careful with his set all wp-config.php modules to Owner, as it is possible the wp-config.php owner change to make customer WP based websites inaccessible.

Another good security measure to  protect your server WordPress based sites from malicious theme template injections (for both personal own hosted wordpress based blog / sites or a WordPress hosting company) is to install and activate WordPress Antivirus plugin.

Adding RSS Feed to WordPress in conjunction with FeedBurner / WordPress add-to-any-subscribe plugin

Saturday, May 15th, 2010

adding_rss_feed_to_wordpress-in-conjunction-with-Google-Feedburner-add-to-any-subscribe-plugin
I received a comment today from one of my blog readers. That he likes my blog content but he looks for a way to subscribe to my blog.
Though I had a subscription button configured in my wordpress template of choice. The button is located on place in the template that is absolutely unnoticable (at the bottom of the page). This is by the way I believe a default behaviour in case if the default wordpress plugin is used.
Thus I decided to set a clear RSS Subscription button on my blog.
Though at a first glimpse the task looked quite trivial it happened to be a way more complex!
I’ve tried a number of things before I can succeed in adding an RSS button.
The most simple though not really flexible way was through:

WordPress’s Widgets (Using the RSS Widget) .
rss default feed widget

This approach however has one major inconvenience.
Using the default wordpress RSS Widget you cannot configure the Widget to keep displaying 0 items of the feed.
In other words you cannot configure from the the sliding menu reading:
How many items would you like to display? 0 in order to prevent completely showing up of any of the feed on the page.
If you leave it with one. The RSS icon of RSS widget would point directly to your blog instead to the RSS feed configured.
So in practice configuring it especially in my case rendered completely useless.
The appearing link from the default RSS widget for some weird reason doesn’t includes a link to where my feed is located https://www.pc-freak.net/blog/feed/
In the meantime I looked online to look for something that will facilitate me in completing the simple task to add an RSS Subscribe Feed to my Blog.
I asked for help in freenode’s irc network #wordpress channel. And a guy from there suggested that I go with wp-o-matic wordpress plugin
Anyways It took me a few minutes to realize this plugin is suitabile if you want to show other blogs feed to your blog instead of adding a RSS feed link to your own blog, this wasn’t my goal so I skipped next in looking for something to help me on.
In the meantime I found the interesting feedburner google feed service that is able to help in creating, publishing and distributing RSS & Atom feeds.
I recommend you check it if you still haven’t. It takes only a few clicks to register in order to use feedburner as a feed service.
Once you are set-up with Feedburner, you can activate all the cool functions, such as allowing your readers to subscribe via email, and also the Feedburner Flares.
Another nice thing about using feedburner is that it formats your fed content in a really pretty layout. By the way since the 2004 feedburner is owned by Google. So in a certain terms using feedburner instead of the default wordpress blog feed will probably attract more google visitors to your blog and is generally good for your blog placement in search engines.
For more of the advantages check feedburner’s google service website .
However there is one major disadvantage in using the feedburner’s feed service. Using the service rob you out of control of your feed, since all the feeds will be properly generated and formatted from feedburner.
The newly created service for feedburner by me is located on www.feeds.feedburner.com/WalkingInLightWithChrist-FaithComputingDiary
Now to be able to use the newly installed feedburner service with my blog I had to test a couple of plugins before I came to the ones that really worked.
I played with feedburner_feedsmith_plugin , feedburner-widget , feedlist.2.61 , wp-keiths-easy-rss , rss-atom-avatar but I couldn’t make any of them work properly with feedburner. Some of the up mentioned plugins were a real hell to configure so I completely abandondoned them seeing their inflexibility. Others were completely abondonede for more than 2 years from now, etc. etc. Fundamentally none of them worked for me.
I finally was able to bring up the feedburner service on my worpdress using The FD Feedburner plugin

All necessery to enable the plugin after you download into wordpress’s wp-content/plugins directory is to configure the plugin from:
Plugins -> FeedBurner Configuration Here is the screenshot on the FD Feedburner plugin configuration screen:

FD Feedburner plugin

As you can see in the screenshot the plugin is really simple to configure. All you need to provide it with is the url provided to you by feedburner right after you register your blog for the service.

Now as you will have your http://www.yourwebsite.com/blog/feed/ be redirected to the feedburner’s website generated feed for your website by the FD FeedBurner WordPress Plugin all left to be done is to provide a link on your blog to your blog feed.

To accomplish this you will have to download the add-to-any-subscribe wordpress plugin.
Again installation of add-to-any-subscribe is a piece of cake, to install follow The install instructions here

Now hopefully your feedburner feed will be able to be distrubuted to your visitors via the AddtoAny subscription button on your blog.

Remove URL from comments in WordPress Blogs and Websites to mitigate comment spam URLs in pages

Friday, February 20th, 2015

remove-comment-spam-url-field-wordpress-website-or-blog-working-how-to
If you're running a WordPress blog or Website where you have enabled comments for a page and your article or page is well indexing in Google (receives a lot of visit / reads ) daily, your site posts (comments) section is surely to quickly fill in with a lot of "Thank you" and non-sense Spam comments containing an ugly link to an external SPAM or Phishing website.

Such URL links with non-sense message is a favourite way for SPAMmers to raise their website incoming (other website) "InLinks" and through that increase current Search Engine position. 

We all know a lot of comments SPAM is generally handled well by Akismet but unfortunately still many of such spam comments fail to be identified as Spam  because spam Bots (text-generator algorithms) becomes more and more sophisticated with time, also you can never stop paid a real-persons Marketers to spam you with a smart crafted messages to increase their site's SEO ).
In all those cases Akismet WP (Anti-Spam) plugin – which btw is among the first "must have"  WP extensions to install on a new blog / website will be not enough ..

To fight with worsening SEO because of spam URLs and to keep your site's SEO better (having a lot of links pointing to reported spam sites will reduce your overall SEO Index Rate) many WordPress based bloggers, choose to not use default WordPress Comments capabilities – e.g. use exnternal commenting systems such as Disqus – (Web Community of Communities), IntenseDebate, LiveFyre, Vicomi

However as Disqus and other 3rd party commenting systems are proprietary software (you don't have access to comments data as comments are kept on proprietary platform and shown from there), I don't personally recommend (or use) those ones, yes Disqus, Google+, Facebook and other comment external sources can have a positive impact on your SEO but that's temporary event and on the long run I think it is more advantageous to have comments with yourself.
A small note for people using Disqos and Facebook as comment platforms – (just imagine if Disqos or Facebook bankrupts in future, where your comments will be? 🙂 )

So assuming that you're a novice blogger and I succeeded convincing you to stick to standard (embedded) WordPress Comment System once your site becomes famous you will start getting severe amount of comment spam. There is plenty of articles already written on how to remove URL comment form spam in WordPress but many of the guides online are old or obsolete so in this article I will do a short evaluation on few things I tried to remove comment spam and how I finally managed to disable URL link spam to appear on site.
 

1. Hide Comment Author Link (Hide-wp-comment-author-link)

This plugin is the best one I found and I started using it since yesterday, I warmly recommend this plugin because its very easy, Download, Unzip, Activate and there you're anything typed in URL field will no longer appear in Posts (note that the URL field will stay so if you want to keep track on person's input URL you can get still see it in Wp-Admin). I'm using default WordPress WRC (Kubrick), but I guess in most newer wordpress plugins is supposed to work. If you test it on another theme please drop a comment to inform whether works for you.  Hide Comment Author Link works on current latest Wordpress 4.1 websites.

A similar plugin to hide-wp-author-link that works and you can use is  Hide-n-Disable-comment-url-field, I tested this one but for some reason I couldn't make it work.

wordpress-remove-delete-hide-n-disable-url-comment-without-deleting-the-form-url-field-screenshot-reduce-comment-spam
Whatever I type in Website field in above form, this is wiped out of comment once submitted 🙂
 

2. Disable hide Comment URL (disable-hide-comment-url)

I've seen reports disable-hide-comment-url works on WordPress 3.9.1, but it didn't worked for me, also the plugin is old and seems no longer maintaned (its last update was 3.5 years ago), if it works for you please please drop in comment your WP version, on WP 4.1 it is not working.

disable-hide-comment-url-screenshot-plugin-to-disable-comment-url-spam-in-wordpress-sites
 


3. WordPress Anti-Spam plugin

WordPress Anti-Spam plugin is a very useful addition plugin to install next to Akismet. The plugin is great if you don't want to remove commenter URL to show in the post but want to cut a lot of the annoying Spam Robots crawling ur site.
 

Anti-spam plugin blocks spam in comments automatically, invisibly for users and for admins.

  • no captcha, because spam is not users' problem
  • no moderation queues, because spam is not administrators' problem
  • no options, because it is great to forget about spam completely

Plugin is easy to use: just install it and it just works.

Anti bot works fine on WP 4.1

4. Stop Spam Comments

Stop Spam Comments is:

  • Dead simple: no setup required, just activate it and enjoy your spam-free website.
  • Lightweight: no additional database queries, it doesn't add script files or other assets in your theme. This means your website performance will not be affected and your server will thank you.
  • Invisible by design: no captchas, no tricky questions or any other user interaction required at all.
     

Stop Spam Comments works fine on WP 4.1.

I've mentioned few of the plugins which can help you solve the problem, but as there are a lot of anti-spam URL plugins available for WP its up to you to test and see what fits you best. If you know or use some other method to protect yourself from Comment Url Spam to share it please.

Import thing to note is it usually a bad idea to mix up different anti-spam plugins so don't enable both Stop Spam Comments and WordPress Anti Spam plugin.

5. Comment Form Remove Url field Manually 

This (Liberian) South) African blog describes a way how to remove URL field URL manually

In short to Remove Url Comment Field manually either edit function.php (if you have Shell SSH access) or if not do it via Wp-Admin web interface:
 

WordPress admin page –> Appearance –> Editor


Paste at the end of file following PHP code:

 

add_filter('comment_form_default_fields', 'remove_url');
 function remove_url($fields)
 {
 if(isset($fields[‘url’]))
 unset($fields[‘url’]);
 return $fields;
 }


Now to make changes effect, Restart Apache / Nginx Webserver and clean any cache if you're using a plugin like W3 Total Cache plugin etc.

Other good posts describing some manual and embedded WordPress ways to reduce / stop comment spam is here and here, however as it comes to my blog, none of the described manual (code hack) ways I found worked on WordPress v. 4.1.
Thus I personally stuck to using Hide and Disable Comment URL plugin  to get rid of comment website URL.

How to get a list and Backup (Save Enabled Plugins) / Restore Enabled (Active) plugins in WordPress site with SQL query

Wednesday, January 14th, 2015

get-list-and-backup-restore-enabled-active-plugins-only-in-wordpress-with-sql-mysql-query

Getting a snapshot of all active plugins and keeping it for future in case if you install some broken plugin and you have to renable all enabled plugins from scratch is precious thing in WordPress.

… It is really annoying when you decide to try to enable few new plugins and out of a sudden your WordPress site / blog starts hanging (when accessed in browser)…

To fix it you have to Disable All Plugins and Re-enable all that used to work. However if you don't keep a copy of the plugins which were previously working and you're like me and have 109 plugins installed of which only 50 are in (Active) state / used. It could take you a day or two until you come up with a similar list to the ones you previously used … Thanksfully there is some prevention you can take by dumping a list of all plugins that are currently active and in later time only enable those in the list.

 

# mysql -u root -p
Enter password:

mysql> USE blog_db;

Here is the output I get in the moment:
 

mysql> DESCRIBE wp_options;
+————–+———————+——+—–+———+—————-+
| Field        | Type                | Null | Key | Default | Extra          |
+————–+———————+——+—–+———+—————-+
| option_id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| option_name  | varchar(64)         | NO   | UNI |         |                |
| option_value | longtext            | NO   |     | NULL    |                |
| autoload     | varchar(20)         | NO   |     | yes     |                |
+————–+———————+——+—–+———+—————-+

 

mysql> SELECT * FROM wp_options WHERE option_name = 'active_plugins';

|        38 | active_plugins | a:50:{i:0;s:45:"add-to-any-subscribe/add-to-any-subscribe.php";i:1;s:19:"akismet/akismet.php";i:2;s:43:"all-in-one-seo-pack/all_in_one_seo_pack.php";i:3;s:66:"ambrosite-nextprevious-post-link-plus/ambrosite-post-link-plus.php";i:4;s:49:"automatic-tag-selector/automatic-tag-selector.php";i:5;s:27:"autoptimize/autoptimize.php";i:6;s:35:"bm-custom-login/bm-custom-login.php";i:7;s:45:"ckeditor-for-wordpress/ckeditor_wordpress.php";i:8;s:47:"comment-info-detector/comment-info-detector.php";i:9;s:27:"comments-statistics/dcs.php";i:10;s:31:"cyr2lat-slugs/cyr2lat-slugs.php";i:11;s:49:"delete-duplicate-posts/delete-duplicate-posts.php";i:12;s:45:"ewww-image-optimizer/ewww-image-optimizer.php";i:13;s:34:"feedburner-plugin/fdfeedburner.php";i:14;s:39:"feedburner-widget/widget-feedburner.php";i:15;s:63:"feedburner_feedsmith_plugin_2.3/FeedBurner_FeedSmith_Plugin.php";i:16;s:21:"feedlist/feedlist.php";i:17;s:39:"force-publish-schedule/forcepublish.php";i:18;s:50:"google-analytics-for-wordpress/googleanalytics.php";i:19;s:81:"google-sitemap-generator-ultimate-tag-warrior-tags-addon/UTWgoogleSitemaps2_1.php";i:20;s:36:"google-sitemap-generator/sitemap.php";i:21;s:24:"headspace2/headspace.php";i:22;s:29:"my-link-order/mylinkorder.php";i:23;s:27:"php-code-widget/execphp.php";i:24;s:43:"post-plugin-library/post-plugin-library.php";i:25;s:35:"post-to-twitter/post-to-twitter.php";i:26;s:28:"profile-pics/profile-pic.php";i:27;s:27:"redirection/redirection.php";i:28;s:42:"scripts-to-footerphp/scripts-to-footer.php";i:29;s:29:"sem-dofollow/sem-dofollow.php";i:30;s:33:"seo-automatic-links/seo-links.php";i:31;s:23:"seo-slugs/seo-slugs.php";i:32;s:41:"seo-super-comments/seo-super-comments.php";i:33;s:31:"similar-posts/similar-posts.php";i:34;s:21:"sociable/sociable.php";i:35;s:44:"strictly-autotags/strictlyautotags.class.php";i:36;s:16:"text-control.php";i:37;s:19:"tidy-up/tidy_up.php";i:38;s:37:"tinymce-advanced/tinymce-advanced.php";i:39;s:33:"tweet-old-post/tweet-old-post.php";i:40;s:33:"w3-total-cache/w3-total-cache.php";i:41;s:44:"widget-settings-importexport/widget-data.php";i:42;s:54:"wordpress-23-related-posts-plugin/wp_related_posts.php";i:43;s:23:"wp-minify/wp-minify.php";i:44;s:27:"wp-optimize/wp-optimize.php";i:45;s:33:"wp-post-to-pdf/wp-post-to-pdf.php";i:46;s:29:"wp-postviews/wp-postviews.php";i:47;s:55:"wp-simple-paypal-donation/wp-simple-paypal-donation.php";i:48;s:46:"wp-social-seo-booster/wpsocial-seo-booster.php";i:49;s:31:"wptouch-pro-3/wptouch-pro-3.php";} | yes      |

Copy and paste this CVS format data to a text file or a Word document for later reference ..

To restore back to normal only active WordPress plugins, first launch following SQL query to disable all enabled wordpress plugins:

UPDATE wp_options SET option_value = 'a:0:{}' WHERE option_name = 'active_plugins';

To restore above "backupped" list of active WP plugins you have to copy paste the saved content and paste it into above UPDATE query substituting option_value=' ' with the backupped string.

P.S. – This query should work on WordPress 3.x on older wordpress ver 2.x use instead:

UPDATE wp_options SET option_value = ' ' WHERE option_name = 'active_plugins';

Because pasting the backupped Active plugins list CSV is a messy and unreadable from command line it is recommended for clarity to use PHPMyAdmin frontend (whenever it is available) on server. This little hint is a real time-saver and saves a lot of headaches. Before proceeding to any Db UPDATE SQL queries always backup your Blog database, with time structure of WordPress data changes!, so in future releases this method might not be working, however if it helped you and works on your version please drop a comment with WordPress version on which this helped you.

Enjoy! 🙂

 

WordPress Plugins to monitor and debug WP enabled plugins – Find Errors / Warnings and Remove WP problematic plugins slowing down your Website (blog) database

Thursday, February 19th, 2015

plugins-to-monitor-debug-wordpress-enabled-plugins-how-to-track-find-errors-and-warnings-and-remove-problematic-wp-extensions-that-slow-down-your-website

Recent days, I'm spending a lot of time again trying to optimize my wordpress blog. Optimizing WP for better efficiency is becoming harder and harder task day by day as the website file content data is growing along with SQL databases. Moreover situation gets even worse because the number of plugins enabled on my blog is incrementally growing with time because, there is more and more goodies I'd like to add.
Optimizing WordPress to run for Speed on a server is a whole a lot of art and its a small universe in itself, because as of time of writting this post the count (number) of WordPress available PLUGINS is 36,197 ! 

1. Manually Tracking WordPress  Plugins causing Slow SQL Queries (MySQL bottleneck) issues directly using console / SSH

Because of its open source development and its nice modular design wordpress has turned into a standard for building small, middle sized and large websites (some WordPress based blogs and sites have from 50 000 to 100 000 unique pages!). My blog is still a small WordPress site with only 1676 posts, so I still haven't reached the high volume traffic optimization requirements but still even though I have a relatively good server hardware  8GB RAM / (2×2.70 Ghz Intel CPU) / 500 GB (7400 RPM HDD) at times I see Apache Webservers is unable to properly serve coming requests because of MySQL database (LEFT JOIN) requests being slow to serve (taking up to few seconds to complete) and creating a MySQL table lock, putting all the rest SQL queries to stay in a long unserved queues line, I've realized about this performance issue by using a a mysql cli (command) client and few commands and console command (tool) called mytop (also known as mtop). MyTop refreshes every 3 seconds, so the slow query will immediately stay on screen to view moer info about it press "f" and type the  in query ID.

mysql-top-running-on-gnu-linux-server-tracking-sql-queries-in-console-screenshot.png

mysql-top-running-on-gnu-linux-server-tracking-sql-queries-in-console-screenshot2

Finally it is very useful to run  for a while MySQL server logging to /var/log/mysql/slow-query.log:
Slow query is enabled (on my Debian 7 Wheezy host) by adding to /etc/mysql/my.cnf
after conf section

 

vim /etc/mysql/my.cnf
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# As of 5.1 you can enable the log at runtime!
#general_log_file        = /var/log/mysql/mysql.log
#general_log             = 1
#
# Error logging goes to syslog due to /etc/mysql/conf.d/mysqld_safe_syslog.cnf.
#
# Here you can see queries with especially long duration

 

Paste:

 

slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 2
log-queries-not-using-indexes

 

And then to make new mysql configuration load restarted mysql server:

 

debian-server:~# /etc/init.d/mysql restart
Stopping MySQL database server: mysqld.
Starting MySQL database server: mysqld ..
Checking for tables which need an upgrade, are corrupt or were
not closed cleanly..

 

Leaving mysql-slow.log to be enabled for 30 minutes to an 1 hrs is a good time to track most problematic slow queries and based on this queries, I took parts of  SQL UPDATE / SELECT / INSERT etc. Db queries which was problematic and grepped throughout /var/www/blog/wp-content/plugin files in order to determine which WordPress Plugin is triggering the slow query, causing blog to hang when too many clients try to see it in browser.

My main problematic SQL query having long execution time  (about 2 to 3 seconds!!!) most commonly occuring in slow-query.log was:

 

SELECT DISTINCT post_title, ID, post_type, post_name FROM wp_posts wposts LEFT JOIN wp_postmeta wpostmeta ON wposts.ID = wpostmeta.post_id LEFT JOIN wp_term_relationships ON (wposts.ID = wp_term_relationships.object_id) LEFT JOIN wp_term_taxonomy ON (wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id) WHERE (post_type='page' OR (wp_term_taxonomy.taxonomy = 'category' AND wp_term_taxonomy.term_id IN(11))) AND post_status = 'publish' AND LENGTH(post_title)>=5 ORDER BY LENGTH(post_title) ASC LIMIT 500

Because above query uses SQL Column names and Tables which are not hard coded in PHP code, to find out which plugins is most probably to launch this complex LEFT JOIN query, I used a quick bash one-liner:

 

# cd /var/www/blog/wp-content/plugins

 

# for i in $(grep -rli 'SELECT DISTINCT' *); do grep -rli 'LEFT JOIN' $i; done 
./seo-automatic-links/seo-links.php
./wp-postviews/wp-postviews.php
./yet-another-related-posts-plugin/classes/YARPP_Cache_Tables.php

 

I wanted to put less load on CPU during grep so looked for string only in .PHP extensioned files with:

 

 # for i in $(find . -iname '*.php' -exec grep -rli 'SELECT DISTINCT' '{}' \;); do grep -rli 'LEFT JOIN' $i; done
./seo-automatic-links/seo-links.php
./wp-postviews/wp-postviews.php
./yet-another-related-posts-plugin/classes/YARPP_Cache_Tables.php


As you can see the complex query is being called from PHP file belonging to one of 3 plugins

  • SEO Automatic Links – this is SEO Smart Links WP plugin (Does internal bliog interlinking in order to boast SEA)
  • WP PostViews – WordPress Post Views plugin (Which allows me to show how many times an article was read in WP Widget menu)
  • Yet Another Related Posts – Which is WP plugin I installed / enabled to show Related posts down on each blog post


2. Basic way to optimize MySQL slow queries (EXPLAIN / SHOW CREATE TABLE)

Now as I have a basic clue on plugins locking my Database, I disabled them one by one while keeping enabled mysql slow query log and viewing queries in mytop and I figure out that actually all of the plugins were causing a short time overheat (lock) on server Database because of LEFT JOINs. Though I really like what this plugins are doing, as they boast SEO and attract prefer to disable them for now and have my blog all the time responsible light fast instead of having a little bit better Search Engine Optimization (Ranking) and loosing many of my visitors because they're annoyed to wait until my articles open

Before disabling I tried to optimize the queries using MySQL EXPLAIN command + SHOW CREATE TABLE (2 commands often used to debug slow SQL queries and find out whether a Column needs to have added INDEX-ing to boast MySQL query).

Just in case if you decide to give them a try here is example on how they're used to debug problematic SQL query:
 

  1. mysql> explain SELECT DISTINCT post_title, ID, post_type, post_name
  2.     -> FROM wp_posts wposts LEFT JOIN wp_postmeta wpostmeta
  3.     -> ON wposts.ID = wpostmeta.post_id LEFT JOIN wp_term_relationships
  4.     -> ON (wposts.ID = wp_term_relationships.object_id) LEFT JOIN wp_term_taxonomy
  5.     -> ON (wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id)
  6.     -> WHERE (post_type='page'
  7.     -> OR (wp_term_taxonomy.taxonomy = 'category'
  8.     -> AND wp_term_taxonomy.term_id IN(11,15,17)))
  9.     -> AND post_status = 'publish'
  10.     -> AND LENGTH(post_title)>=5
  11.     -> ORDER BY LENGTH(post_title) ASC
  12.     -> LIMIT 500;
  13. +—-+————-+———————–+——–+——————+———+———+———————————————+——+———————————————-+
  14. | id | select_type | table                 | type   | possible_keys    | key     | key_len | ref                                         | rows | Extra                                        |
  15. +—-+————-+———————–+——–+——————+———+———+———————————————+——+———————————————-+
  16. |  1 | SIMPLE      | wposts                | ALL    | type_status_date | NULL    | NULL    | NULL                                        | 1715 | Using where; Using temporary; Using filesort |
  17. |  1 | SIMPLE      | wpostmeta             | ref    | post_id          | post_id | 8       | blog.wposts.ID                              |   11 | Using index; Distinct                        |
  18. |  1 | SIMPLE      | wp_term_relationships | ref    | PRIMARY          | PRIMARY | 8       | blog.wposts.ID                              |   19 | Using index; Distinct                        |
  19. |  1 | SIMPLE      | wp_term_taxonomy      | eq_ref | PRIMARY          | PRIMARY | 8       | blog.wp_term_relationships.term_taxonomy_id |    1 | Using where; Distinct                        |
  20. +—-+————-+———————–+——–+——————+———+———+———————————————+——+———————————————-+
  21. 4 rows in set (0.02 sec)
  22.  
  23. mysql>
  24.  

     

     

  1. mysql> show create table wp_posts;
  2. +———-+————————–+
  3. | Table    | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                 |
  4. +———-+————————–+
  5. | wp_posts | CREATE TABLE `wp_posts` (
  6.   `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  7.   `post_author` bigint(20) unsigned NOT NULL DEFAULT '0',
  8.   `post_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  9.   `post_date_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  10.   `post_content` longtext NOT NULL,
  11.   `post_title` text NOT NULL,
  12.   `post_excerpt` text NOT NULL,
  13.   `post_status` varchar(20) NOT NULL DEFAULT 'publish',
  14.   `comment_status` varchar(20) NOT NULL DEFAULT 'open',
  15.   `ping_status` varchar(20) NOT NULL DEFAULT 'open',
  16.   `post_password` varchar(20) NOT NULL DEFAULT '',
  17.   `post_name` varchar(200) NOT NULL DEFAULT '',
  18.   `to_ping` text NOT NULL,
  19.   `pinged` text NOT NULL,
  20.   `post_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  21.   `post_modified_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  22.   `post_content_filtered` longtext NOT NULL,
  23.   `post_parent` bigint(20) unsigned NOT NULL DEFAULT '0',
  24.   `guid` varchar(255) NOT NULL DEFAULT '',
  25.   `menu_order` int(11) NOT NULL DEFAULT '0',
  26.   `post_type` varchar(20) NOT NULL DEFAULT 'post',
  27.   `post_mime_type` varchar(100) NOT NULL DEFAULT '',
  28.   `comment_count` bigint(20) NOT NULL DEFAULT '0',
  29.   PRIMARY KEY (`ID`),
  30.   KEY `post_name` (`post_name`),
  31.   KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
  32.   KEY `post_parent` (`post_parent`),
  33.   KEY `post_author` (`post_author`),
  34.   FULLTEXT KEY `post_related` (`post_title`,`post_content`)
  35. ) ENGINE=MyISAM AUTO_INCREMENT=12033 DEFAULT CHARSET=utf8 |
  36. +———-+———————-+
  37. 1 row in set (0.00 sec)
  38.  
  39. mysql>
  40.  


By the way above output is a paste from the the new PasteBin Open Source (Stikked powered) service I started on www.pc-freak.net – paste.www.pc-freak.net (p.www.pc-freak.net) 🙂

Before I took final decision to disable slow WP plugins, I've experimented a bit trying to add INDEX to Table Column (wposts) in hope that this would speed up SQL queries with:

 

mysql> ALTER TABLE TABLE_NAME ADD INDEX (wposts);

 

But this didn't improve query speed even on the contrary it make execution time worse.

3. Tracking WordPress Plugin PHP Code Execution time and Plugins causing Slow SQL Queries (MySQL bottleneck) issues through WP itself

Well fine, I'm running my own hosted Blog and WordPress sites, but for people who have wordpress sites on shared hosting, there is usually no SSH (Terminal) Access to server, those people will be happy to hear there are 2 Free easy installable WordPress plugins which can be used to Debug Slow WordPress Plugins SQL Queries as well as plugin to Track which plugin takes most time to execute, this are:
 

 

a) P3 Plugin Performance Profiler  

runs a scan over your site to determine what resources your plugins are using, and when, during a standard page request. P3 PPP Can even create reports in a beatiful Excel like Pie chart sheet.

p3-plugin-performance-profiler-godaddy-screenshot-debian-gnu-linux-wordpress-website

Another useful thing to see with P3 PPP is Detailed Timeline it shows when the plugins are being loaded during new page request so you can see if there is a certain sequence in time when a plugin slows down the website.

detailed_timeline-wordpress-p3-performance-plugin-on-website-screenshot

The pictures says it all as P3 PPP is Godaddy's work, congrats to GoDaddy, they've done great job.

 

b) WordPress memory Viewer WP plugins

Is useful to check how much memory each of WordPress plugin is taking on user (visitor) request.
Memory Viewer is allows you to view WordPress’ memory utilization at several hooks during WordPress’ execution. It also shows a summary of MySQL Queries that have ran as well as CPU time.
To use it download it to plugins/ folder as usual enable it from:

Installed Plugins -> (Inactive) -> Memory Viewer (Enable)

To see statistics from Memory Viewer open any post from your blog website and scroll down to the bottom you will notice the statistics, showing up there, like on below screenshot.

wordpress-memory-viewer-plugin-debian-gnu-linux-hosted-website-show-which-plugin-component-eats-most-memory-in-wordprses-blog
 

Though WP Memory Viewer is said to work only up to WP version 3.2.1, I've tested it and it works fine on my latest stable WordPress 4.1 based blog.

c) WordPress Query Monitor

wordpress-query-monitor-plugin-to-monitor-track-and-optimize-problems-with-sql-caused-by-wp-plugins.png
 

Query Monitor is a debugging plugin for anyone developing with WordPress but also very helpful for anyone who want to track issues with plugins who use the database unefficient.
It has some advanced features not available in other debugging plugins, including automatic AJAX debugging and the ability to narrow down things by plugin or theme.
You can view plenty of precious statistics on how enabled plugins query the database server, here is a short overview on its Database Queries capabilities:

  • Shows all database queries performed on the current page
  • Shows affected rows and time for all queries
  • Show notifications for slow queries and queries with errors
  • Filter queries by query type (SELECT, UPDATE, DELETE, etc)
  • Filter queries by component (WordPress core, Plugin X, Plugin Y, theme)
  • Filter queries by calling function
  • View aggregate query information grouped by component, calling function, and type
  • Super advanced: Supports multiple instances of wpdb on one page
  • Once enabled from Plugins you will see it appear as a new menu on bottom Admin raw.

An important note to make here is latest Query Monitor extension fails when loaded on current latest Wordpress 4.1, to use it you will have to download and useolder Query Monitor plugin version 2.6.8 you can download it from here

d) Debug Bar

If you want you want a Memory Viewer like plugin for more complex used components memory debugging, reporting if (WP_DEBUG is set in wp-config.php) also check out Debug Bar .
For me Debug Bar was very useful because it show me depreciated functions some plugins used, so I substituted the obsoleted function with new one.

 

debug-bar-debug-wordpress-plugins-memory-use-screenshot-website


4. Server Hardware hungry (slow) WordPress plugins that you better not use

While spending time to Google for some fixes to WP slow query plugins – I've stumbled upon this post giving a good list with WordPress Plugins better off not to use because they will slow down your site
This is a publicly well known list of WP plugins every WordPress based site adminstrator should avoid, but until today I didn't know so my assumption is you don't know either ..

Below plugins are extremely database intensive mentioned in article that we should better (in all cases!) avoid:

  • Dynamic Related Posts
  • SEO Auto Links & Related Posts
  • Yet Another Related Posts Plugin
  • Similar Posts
  • Contextual Related Posts
  • Broken Link Checker — Overwhelms even our robust caching layer with an inordinate amount of HTTP requests.
  • MyReviewPlugin — Slams the database with a fairly significant amount of writes.
  • LinkMan — Much like the MyReviewPlugin above, LinkMan utilizes an unscalable amount of database writes.
  • Fuzzy SEO Booster — Causes MySQL issues as a site becomes more popular.
  • WP PostViews — Inefficiently writes to the database on every page load. To track traffic in a more scalable manner, both the stats module in Automattic’s Jetpack plugin and Google Analytics work wonderfully.
  • Tweet Blender — Does not play nicely with our caching layer and can cause increased server load.


A good Complete list of known WordPress slow plugins that will hammer down your wordpress performance is here

There are few alternatives to this plugins and when I have some free time I will download and test their alternatives but for now I plan the plugins to stay disabled.
 

For the absolute WP Performance Optimization Freaks, its good to check out the native way to Debug a wordpress installation through using few embedded
variables

 

define('WP_DEBUG', true);
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
define('SAVEQUERIES', true);

 

An article describing how you can use native WP debug variables is here


Happy Optimizing  ! 🙂

How to disable WordPress Visual Editor to solve problems Editor / Post problems after upgrade to WordPress 4.0

Monday, October 27th, 2014

wordpress-visual-editor-not-showing-problem-and-its-easy-fix-solution
Recently, I've upgraded to latest as of time of writting WordPress 4.0. The upgrade went fine however after upgrade even though I've upgraded also the CKEdit for WordPressVisual Editor stopped working. To solve the issue, my logical guess was to try to disable CKEditor:

(Plugins -> Ckeditor for WordPress (Deactivate)

However even after disabling, default WP Visual Editor continued to be not showing properly – e.g. the Publish / Save Draft / Preview buttons pane as well as the usual format text menu buttons (set text to Italic, Bold, Underline Text,  Create New Paragraph etc.) was completely missing and it was impossible to write anything in the text edit box like you see in below screenshot:

wordpress_visual_editor_missing_buttons_no-publish-button-wordpress_screenshot

I've red a lot on the internet about the issue and it seem a lot of people end up with the WordPress broken Visual Editor issue after upgrading to WP 3.9 and to WordPress 4.0. A lot of people did came to a fix, by simply disabling all WP plugins and enabling them one by one, however as I have about 50 WordPress plugins enabled in my WP blog disabling every plugins and re-enabling was too time consuming as I had to first write down all the plugins enabled and then re-enable them one by one by hand (after re-installing the wordpress version) testing after each whether the editor works or not ..
Therefore I skipped that fix and looked for another one. Other suggestions was to:

Edit wp-includes/css/editor.min.css and include at the end of file:
 

.mce-stack-layout{margin-top:20px}.wp-editor-container textarea.wp-editor-area{margin-top:67px;}


I've tried that one but for me this didn't work out ..

There were some people reporting certain plugins causing the visual editor issues such reported were:

  • NextScripts: Social Networks Auto-Poster
  • Google Sitemaps – Append UTW Tags
  • Google XML Sitemaps
  • TinyMCE Advanced (some suggested replacing TinyMCE and related scripts)
  • JS & CSS Script Optimizer … etc.
     

There were some suggestions also that the issues with Editor could be caused by the Used Blog Theme. It is true I'm using very Old WordPress theme, however as I like it so much I didn't wanted to change that one ..

Others suggested as a fix adding to site's wp-config.php:

define('CONCATENATE_SCRIPTS', false);

Unfortunately this doesn't work either.

Finally I've found the fix myself, the solution is as simple as disabling WordPress Visual Editor:

To disable WP Visual Editor:

1. Go to Upper screen right corner, after logged in to wp-admin (A drop down menu) with Edit My Profile will appear::

wordpress_edit_my_profile_screenshot
2. From Profile screen to appear select Disable the visual editor when writing scroll down to the bottom of page and click on Update Profile button to save new settings:

disable_the_visual_editor_when_writing

That's all now the Post / Edit of an Article will work again with text buttons only.

Manually deleting spam comments from WordPress blogs and websites to free disk space and optimize MySQL

Monday, November 24th, 2014

WordPress-delete_spam_comments_manually_with_sql_query_to-optimize_mysql-and-free-disk-space
If you're a web-hosting company or a web-development using WordPress to build multitudes of customer blogs or just an independent blogger or sys-admin with a task to optimize a server's MySQL allocated storage  / performance on triads of WordPress-es a a good tip that would help is to removing wp_comments marked as spam.

Even though sites might be protected of thousands of spam message daily caught by WP anti-spam plugin Akismet, spam caught messages aer forwarder by Akismet to WP's Spam filter and kept wp_comments table with comments_approved column  record 'spam'.

Therefore you will certainly gain of freeing disk space uselessly allocated by spam messages into current MySQL server storage dir (/var/lib/mysql   /usr/local/mysql/data – the directory where my.cnf tells the server to keep its binary data .MYI, .MYD, .frm files) as well as save a lot of disk space by excluding the useless spam messages from SQL daily backup archives.

Here is how to remove manually spam comments from a WordPress blog under database (wp_blog1);

mysql> use wp_blog1;
mysql> describe wp_comments;
+———————-+———————+——+—–+———————+—————-+
| Field | Type | Null | Key | Default | Extra |
+———————-+———————+——+—–+———————+—————-+
| comment_ID | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| comment_post_ID | bigint(20) unsigned | NO | MUL | 0 | |
| comment_author | tinytext | NO | | NULL | |
| comment_author_email | varchar(100) | NO | | | |
| comment_author_url | varchar(200) | NO | | | |
| comment_author_IP | varchar(100) | NO | | | |
| comment_date | datetime | NO | | 0000-00-00 00:00:00 | |
| comment_date_gmt | datetime | NO | MUL | 0000-00-00 00:00:00 | |
| comment_content | text | NO | | NULL | |
| comment_karma | int(11) | NO | | 0 | |
| comment_approved | varchar(20) | NO | MUL | 1 | |
| comment_agent | varchar(255) | NO | | | |
| comment_type | varchar(20) | NO | | | |
| comment_parent | bigint(20) unsigned | NO | MUL | 0 | |
| user_id | bigint(20) unsigned | NO | | 0 | |
+———————-+———————+——+—–+———————+—————-+


The most common and quick way useful for scripting (whether you have to do it for multiple blogs with separate dbs) is to delete all comments being filled as 'Spam'.

To delete all messages which were filled by Akismet's spam filter with high probabily being a spam issue from mysql cli interface:

DELETE FROM wp_comments WHERE comment_approved = 'spam';


For Unread (Unapproved) messages the value of comment_approved field are 0 or 1, 0 if the comment is Red and Approved and 1 if still it is to be marked as read (and not spam).
If a wordpress gets heavily hammered with mainly spam and the probability that unapproved message is different from spam is low and you want to delete any message waiting for approvel as not being spam from wordpress use following SQL query:

DELETE FROM wp_comments WHERE comment_approved = 0;

Another not very common you might want to do is delete only all apprved comments:

DELETE FROM wp_comments WHERE comment_approved = 1;

For old installed long time unmaintained blogs (with garbish content), it is very likely that 99% of the messages might be spam and in case if there are already >= 100 000 spam messages and you don't have the time to inspect 100 000 spam comments to get only some 1000 legitimate and you want to delete completely all wordpress comments for a blog in one SQL query use:

TRUNCATE wp_comments;

Another scenario if you know a blog has been maintained until certain date and comments were inspected and then it was left unmaintained for few years without any spam detect and clear plugin like Akismet, its worthy to delete all comments starting from the date wordpress site stopped to be maintained:

DELETE FROM wp_comments WHERE comment_date > '2008-11-20 05:00:10' AND comment_date <= '2014-11-24 00:30:00'

How to determine WordPress blogs with most spam on multiple blog hosting server

Thursday, November 27th, 2014

determine_find_blogs_with_most_spam-on-multiple-wordpress-blogs-hosting-server-stop-and-clea-large-amounts-ofrcomment-spam
If you're a hosting company that is hosts Joomla / WordPress / ModX websites (each) on separate servers and thus you end up with servers hosting multiple WordPress customer Blogs only, lets say (100+ WP blogs per host) soon your MySQL blogs databases will be full (overfilled) with spam comments. Blogs with multitude of spam comments reduces the WordPress site attractiveness, takes useless disk space, makes wp databases hard to backup and slowing drastically the SQL server.

As our duty as system administrators is to keep the servers optimized (improve performance) and prevent spam-bots to hammer your Linux servers, its is always a good idea to keep an eye on which hosted blogs attract more spammers and cause server overheads and bad hardware optimization.

WordPress blogs keeps logged comments under database_name.wp_comments  (table) thus the quickest way to find out blogs with largest comments tables is to use Linux's find command and print out only comments tables larger than set size.

Here is how:

find /var/lib/mysql/ -type f -size +1024k -name "*_comments.MYD" -exec ls -lh {} ; | awk '{ print $9 ": " $5 }'


/var/lib/mysql/funny-blog/wp_comments.MYD: 15,7M
/var/lib/mysql/wordblogger/wp_comments.MYD: 5,3M
/var/lib/mysql/loveblog/wp_comments.MYD: 50,5M

A comments database of 1MB means about at least 500+ comments, thus the blog loveblog's wp_comments.MYD = 50,5 Mbs contains probably about 10000! comments and should be definitely checked in a browser, if its overfilled with spam because of bad anti-spam policy or missing currently best wordpress spam catcher plugin Akismet. In cases of lack of client to protect his spam you can write quickly a script to auto mail him and ask him kindly to check / fix his blog spam.
In some cases it is useful to write a few liners bash script to automatically disable users with extraordinary blog spam comments databases (quickest way to do it is to move users blog data under quarantine directory and adding a Blog Suspended static html webpage with text like "Please contact support for more info".

1024k find arguments is 1MB, on a big hosted blogs this might be low and you might want to use (100Mb) = 102400kbytes.
You should note that *_comments.MYD in above find cmd is because though standardly wordpress sets wp_ as a prefix to its created skele table structures it is not always the case. 

In above command example find looks for spam comments in /var/lib/mysql (because this is a Debian Linux server), however on other MySQL custom installs, it might be in another dir i.e. /usr/local/mysql/data etc.

It is useful to set the wp_comments statistics output to execute at least once a day as a cronjob:

crontab -u root -e 00 24 * * * /usr/sbin/check_spammed_blogs.sh

vim /usr/check_soammed_blogs.sh

Set a script like:

#!/bin/sh
find /var/lib/mysql/ -type f -size +1024k -name "*_comments.MYD" -exec ls -lh {} ; | awk '{ print $9 ": " $5 }' | tee -a /var/log/blogs_with_most_spam_comments.log

Though above commands is to run on GNU / Linux, for Windows servers based hosting you can  install GNUWin tools and adapt above cmd using windows standard commands or PowerShell to do the same.
Finally you can might want to use some other SQL script to clear blogs with enormously large tables from spam or clear all unapproved spam comments