Portable Wordpress

25 Aug 2017 in Wordpress

Many times I've seen developers on wordpress struggling when transferring the installation from a development/staging environment to production.

One tip is to use the WP_HOME and WP_SITEURL constants as defined in wp-config.php when creating static links.

So instead of using something like this:

<a href="http://example.com/a-link">

Use

<a href="<?= WP_SITEURL ?>/a-link">

Of course this applies only to PHP files.

For css you can take advantage of HTML <base> element somewhere in your html head like this:

<base href="<?= WP_SITEURL ?>">

Any resource, like background images, referenced in css will be relative to the url above and you don't have to mess with absolute urls any more.

Beware that the usage of an anchor tag is resolved by using the base url as reference and triggers an http request to the base url. To circumvent that, you may use absolute resources in css at the cost of not developing in subfolders anymore.

Troubleshooting a SIGKILL

17 Jul 2017 in ConfigServer, SIGKILL

Recently I was called to investigate a problem where a PHP script stopped working after a random amount of time. It was a long running script interacting with mysql and it was called from both the webserver (apache via suphp) and the command line.

To give you some context the script was badly written, continuing the tradition of how bad the PHP as a programming language can be - of course this is mainly the programmer's fault:

ignore_user_abort(true);    
// the end of time is coming

set_time_limit(0);          
// who cares if the server is fucked up

error_reporting(E_ALL ^ E_DEPRECATED ^ E_NOTICE ^ E_WARNING);
// we don't care about warnings - of course *WE* introduced them

ini_set('display_errors', 'On'); 
// yes, display errors on the production server

mysql_query("SET NAMES = 'greek'");
mysql_query("set character_set_connection=greek");
mysql_query("set character_set_client=greek");
mysql_query('set character set greek');
mysql_query('set character_set_results greek');
mysql_query('SET wait_timeout=28800;');
// because we don't exactly know which one is working,
// just try out all possible permutations

function my_file_get_contents($url)
{
    $filename = $url;
    $handle = fopen($filename, "r");
    $contents = fread($handle, filesize($filename));
    fclose($handle);
    return $contents;
}
// is this code so old considering that file_get_contents
// is in PHP core since 4.3.0?

The linux server was setup (and managed) with CPanel from some hosting company with operators doing things like this (excerpt from .bash_history):

wall Is any one working on the server
wall <some username>
chmod 777 /on/some/publicly/available/file-from-webserber

Add on top of that the absense of any kind of manual about installed packages, customizations, checklists, policies, security, etc, and things gets interesting pretty quickly.

Back to the problem: After trying the script with nothing written in Apache/PHP error log about a possible error (of course I changed error_reporting to E_ALL), I switched to command line in order to find out what was happening:

php the-offending-script
<some output>
Killed

Killed? WTF!

Ok, let's look at kernel messages, is this run out of memory? Did the oom killer kick in? Unfortunatelly no, everything seemed fine. Is MySQL low on connections? Increased, no solution. Watched memory footprint via memory_get_usage(). Nothing suspicious. Next step to try with strace but again no usable hint.

The script was killed with an exit code of 137 (that is 128 + 9) which means it received the SIGKILL signal. So I increased user limits - or more preciselly disabling the limits cpanel software has introduced. Still the script was killed at random points.

Confused, I tail'd all of the /var/log/*.log, run the script and voilla:

Jul 17 XX:XX:XX host lfd[31295]: *User Processing* PID:24845 Kill:1 User:XXX RSS:457(MB) EXE:/usr/local/bin/php CMD:php the-offending-script

This is from a file called /var/log/lfd.log and it turned out its part of the ConfigServer package. What this does is to kill a process when it's above a memory limit, time limit or a number of processes per user limit - in this case it was the memory.

The fun part was that the comments in the configuration file at /etc/csf/csf.conf about "Process Tracking" shows a warning about not enabling this:

Warning: We don't recommend enabling this option unless absolutely necessary as it can cause unexpected problems when processes are suddenly terminated. It can also lead to system processes being terminated which could cause stability issues. It is much better to leave this option disabled and to investigate each case as it is reported when the triggers above are breached

So I just set the PT_USERKILL to "0", restarted the LFD daemon via /etc/init.d/lfd restart and problem solved!

PS: I forgot to tell you that no email was set in CSF configuration to receive these warnings. How awesome is that?

GnuPlot in your toolset

06 Jul 2017 in gnuplot

Recently I was asked to investigate a web server issue not responding in regural intervals.

After spending some time digging around in logs and configs, I developed a solution to log the server load at small time intervals in order to have a better view of what's happening.

To do this, create a very simple shell script to store the time and server load:

#!/bin/bash
echo date +%Y%m%d-%H%M%S >> report/uptime.log
uptime >> uptime.log

Then run this script at an interval of 5 secs:

while true; do echo -en . ; bash report.sh ; sleep 5; done

When enough data has gathered, prepare for use with gnuplot:

cat uptime.log \
    | sed 'N;s/\n/ /' \
    | cut -d' ' -f1,15 \
    | sed -s 's/,//g' > uptime.plot

And plot it:

gnuplot -p -e '
    set xdata time;
    set timefmt "%Y%m%d-%H%M%S";
    plot "uptime.plot" using 1:2;
'

Making sense of Minimum Viable Product

21 Jun 2017 in Other

An article about workflow optimization and making the customer happy:

Many projects fail badly because they do Big Bang delivery, or building until the project is 100% done before delivering at the end. A lot of time has passed without any actual user testing, so the product is most likely riddled with design flaws based on incorrect assumptions about what people need.

The author presents a different approach:

We focus on the underlying need the customer wants fulfilled. In response to the underlying need, the team delivers the smallest thing they can think of that will get the customer testing things and giving us feedback.

We're not trying to make the customer happy at this point. We might make a few early adopters happy (or pragmatists in pain), but our main goal at this point is just to learn

No matter how much up-front analysis you do, you’re still surprised when you put the first real release into the hands of a real user, and many of your assumptions turn out to be way off.

So, do some up-front analysis, discover as much as you can before starting development. But don't spend too much time on it and don't trust the analysis too much - start prototyping and releasing instead.

And shares some real life examples based on Spotify, Minecraft, a Goverment project and LEGO.

You can read the whole article at everup.com

Interacting with a Magento database directly

15 Jun 2017 in Magento

Sometimes you may need to interact directly with the database of a Magento installation without using any models.

For this to work you may get the core sql adapter with:

$db = Mage::getSingleton("core/resource")
    ->getConnection("core_write"); // or "core_read" for reading

and use it like this:

$query = "INSERT INTO table(fields) VALUES (:values)";
$binds = ['values' => 'foo'];
$db->query($query, $binds);

Optimizing wordpress websites

13 Jun 2017 in Wordpress

On Smashing Magazine, Brian Jackson has posted an article about wordpress optimization

I have compiled a list of bad web practices and recommendations on what not to do on your site, based on thousands of hours of customer interactions, support tickets, and troubleshooting I experience on a daily basis. Some of these range from beginner mistakes to more complex issues...

and shares his list of do's and don'ts:

  • Switching Hosts Isn't Always a Quick Fix. If your WordPress site is having code issues or compatibility problems with specific plugins, this is still going to occur no matter where you host your site.
  • Live Sites are Not For Development Work. Use a local development environemt.
  • Not A Developer? Don't Edit Your Code.
  • Don't Cut Corners on Your Themes and Plugins. Try to stick with reputable developers when choosing plugins and look through the ratings and reviews beforehand
  • Watch Your Admin AJAX Calls.
  • Be Smart With Ad Networks and Limit External Services.
  • Over Optimizing Can Hurt Your Performance.
  • Common Performance Issues are Easy to Diagnose
  • Modifying WordPress Core is Bad
  • Ensure PHP 7/HHVM Compatibility Before Jumping on Board
  • Large Sites Should Optimize Their Database. Disable or modify the number of revisions you keep in your database
  • Do You Really Need a Multipurpose Theme?
  • Error Log Is Your Friend
  • Google is Here for a Reason
  • 123456 Is No Longer Acceptable
  • Scripts Don’t Always Need to Load Sitewide

Read the whole article at www.smashingmagazine.com/2017/06/better-faster-optimized-wordpress-websites/

Learning JavaScript design patterns

13 Jun 2017 in Books, Javascript

A book by Addy Osmani, engineering manager at Google.

Design patterns are reusable solutions to commonly occurring problems in software design. They are both exciting and a fascinating topic to explore in any programming language.

One reason for this is that they help us build upon the combined experience of many developers that came before us and ensure we structure our code in an optimized way, meeting the needs of problems we're attempting to solve.

Design patterns also provide us a common vocabulary to describe solutions. This can be significantly simpler than describing syntax and semantics when we're attempting to convey a way of structuring a solution in code form to others.

Available online at https://addyosmani.com/resources/essentialjsdesignpatterns/book/

isset and empty in PHP

05 Jun 2017 in PHP

Sometimes you may be in confusion about the proper use of isset and empty functions in PHP when testing for the existence of a variable, array key or object property.

For these two functions, the PHP manual states:

isset: Determine if a variable is set and is not NULL. If multiple parameters are supplied then isset() will return TRUE only if all of the parameters are set. Evaluation goes from left to right and stops as soon as an unset variable is encountered.

empty: Determine whether a variable is considered to be empty. A variable is considered empty if it does not exist or if its value equals FALSE. empty() does not generate a warning if the variable does not exist.

Because the check for NULL in isset is using the identity comparison (===), while in empty the equality comparison (==) is used, it may sometimes lead to unexpected behaviour from a programmer's point of view.

My preference in general is to use empty (which can be seen as a shorthand for !isset($var) || !$var) and use isset when trying to access keys in arrays or properties in objects.

As an example, look at the following:

                            | isset() | empty() |
                            |---------|---------|
$foo                        | false   | true    |
$null        = null;        | false   | true    |
$false       = false;       | true    | true    |
$true        = true;        | true    | false   |
$emptyString = "";          | true    | true    |
$arr         = [];          | true    | true    |
$array       = ['k'=>'v'];  | true    | false   |
               $array['k']  | true    | false   |
               $array['X']  | false   | true    |

Meanwhile: Javascript

25 May 2017 in Javascript, Fun

I can't resist on this (kudos to https://twitter.com/lukaseder/status/867080556470730752):

> '5' - 3
2
> '5' + 3
'53'
> '5' - '4'
1
> '5' + + '5'
'55'
> 'foo' + + 'foo'
'fooNaN'
> '5' + - '2'
'5-2'
> '5' + - + - - + - - + + - + - + - + - - - '-2'
'52'
> var x = 3;
undefined
> '5' + x - x
50
> '5' - x + x
5

This is called type coersion (in javascript) and can bite you hard if you aren't aware of this.

What about PHP (the 5.6 version):

php > echo '5' - 3;
2
php > echo '5' + 3;
8
php > echo '5' - '4';
1
php > echo '5' + + '5';
10
php > echo 'foo' + + 'foo';
0
php > echo '5' + - '2';
3
php > echo '5' + - + - - + - - + + - + - + - + - - - '-2';
7
php > $x = 3;
php > echo '5' + $x - $x;
5
php > echo '5' - $x + $x;
5

And Python:

>>> '5' - 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'str' and 'int'

OK, got the point, no need to continue...