Auto detecting PHP version for CLI

As more customers start to take advantage of both M1 and M2 (and the benefits of running M1 on PHP7), they soon realise the massive potential of native simultaneous multi-PHP support in MageStack. But with great power can come a need to make life easier.

Working with Multi PHP

Its possible to manually select a PHP version just by using the version name as the binary, so instead of doing something like this,

php foo.php

You can specify the version as the binary name,

php-5.4 foo.php  # Executes as PHP 5.4
php-5.5 foo.php  # Executes as PHP 5.5
php-5.6 foo.php  # Executes as PHP 5.6
php-7.0 foo.php  # Executes as PHP 7.0
php-7.1 foo.php  # Executes as PHP 7.1

But remembering what site uses what PHP version can become tricky if you've got a multi-tenant stack using many separate domain groups each running their own version of PHP.

Auto-selecting PHP

So given a quick after-hours challenge, a customer asked if there was an easy way to auto select the PHP version based on either the path supplied for the script, or the current working directory; so I put together a proof of concept.

function php()
{
    local dg bin_dir

    # Determine domain group and php version from arguments
    dg=$(echo "$@" | ack-grep "/microcloud/(data/)?domains/([^/]+)" --output='$2')

    # Failing that, try the current working directory
    if [ -z "$dg" ]; then
        dg=$(readlink -f . | ack-grep "/microcloud/(data/)?domains/([^/]+)" --output='$2')
    fi

    bin_dir="/microcloud/domains/$dg/usr/bin"

    # Execute the command
    if [ -f "$bin_dir/php" ]; then
        (
            export PATH="$bin_dir:$PATH"
            $(which php) "$@"
        )
    else
        /usr/bin/php "$@"
    fi
}

The above method can be dropped into ~/.bash_profile for interactive use (eg. via SSH), or even placed into /usr/local/bin/php for non-interactive use (eg. via cron).

Then, its just a case of invoking your script using php either being in the correct directory - or by including the full path of the file being executed.

Examples

The default PHP version is 5.4 and I've made two domain-groups, each with their own respective PHP version,

  • phpfiv (running PHP 5.6)
  • phpsev (running PHP 7.1)

Testing out the default version,

[www-data@acc1 .microcloud ~]
[~]$ php -v
PHP 5.4.45 (cli) (built: Jan 24 2017 11:42:45)

Then if you enter a specific domain group and running the same command - you'll notice the PHP version is auto selected based on that domain-group,

[www-data@acc1 .microcloud ~]
[~]$ cd /microcloud/domains/phpsev
[www-data@acc1 .microcloud /microcloud/domains/phpsev/domains]
[domains]$ php -v
PHP 7.1.1 (cli) (built: Jan 23 2017 17:06:36)

Or if you specify the full path to the script you want to run,

[www-data@acc1 .microcloud ~]
[~]$ php /microcloud/domains/phpfiv/domains/example.com/http/test.php
PHP 5.6.30 (cli) (built: Jan 20 2017 11:39:49)

And as if by magic, the right version of PHP is selected each time. I'll shore up this functionality and look to push it into the master branch of MageStack for all customers to use.