Fix: Highcharts x-Axis Timestamp Labels Not Matching Data

Standard

Background – Highcharts

I kept running into an issue where I was extracting data from a database and loading it into HighCharts/HighStock. This was a great, fast and simple solution to graphically represent the statistics of some of my systems. Unfortunately, when I broke the stats down by 5-minute intervals, I noticed that the irregular datetime labels on the x-Axis were off by about 5 hours. After looking around Google for quite some time, I stumbled upon the following fix: useUTC: false.

The Fix

To fix this issue, place the following above your highcharts javascript:

[javascript]
Highcharts.setOptions({
global: {
useUTC: false
}
});
[/javascript]

Cron Job Manager

Standard

Cron Jobs

Any sysadmin with a hope to grow their future has come across cron jobs. They are at the fundamental core of a working system.

The Code

I still need to add doc blocks and examples, but here’s code to wet your lips.

[php]
class CronManager{
/* replace with the cron prefix you wish to run */
var $prefix_path = 'php -f file.php';

public function __construct($cron_file){
$this->cron_file = $cron_file;
$this->header[] = “######################################################”;
$this->header[] = “#”;
$this->header[] = “# Automatic Crontab Manager”;
$this->header[] = “# Created Automagically On: “.date(‘F j, Y, g:i a’);
$this->header[] = “# Filename: “.$this->cron_file;
$this->header[] = “# Author – Mike Mackintosh – www.highonphp.com”;
$this->header[] = “#”;
$this->header[] = “######################################################”;

if(file_exists(‘/etc/cron.d/’.$this->cron_file)){
exec(‘sudo chmod 777 /etc/cron.d/’.$this->cron_file, $output);
}
else{
exec(‘sudo touch /etc/cron.d/’.$this->cron_file .’ && sudo chmod 777 /etc/cron.d/’.$this->cron_file, $output);
}
}

public function add_time($minute, $hour, $day, $month, $week, $app_path = NULL){
$this->line[] = “$minute $hour $day $month $week root {$this->prefix_path} $app_path”;
}

public function clean(){
file_put_contents(‘/etc/cron.d/’.$this->cron_file, ”);
}

public function save(){
file_put_contents(‘/etc/cron.d/’.$this->cron_file, implode(“\n”, $this->header).”\n\n” . implode(“\n”, $this->line).”\n\n”);
}

public function __destruct(){
exec(‘sudo chmod 644 /etc/cron.d/’.$this->cron_file);
exec(‘sudo touch /etc/cron.d’);
}

public function decode(){
$content = file_get_contents(‘/etc/cron.d/’.$this->cron_file);
$lines = explode(“\n”, $content);
$i = 1;
foreach($lines as $line){
if(substr($line, 0, 1) != ‘#’ && $line != ”){
$part = explode(“\t”, $line);
$output[$i] = array(‘Minute’ => $part[0], ‘Hour’ => $part[1], ‘Day’ => $part[2], ‘Month’ => $part[3], ‘Week’ => $part[4], ‘User’ => $part[5], ‘File’ => str_replace($this->prefix_path, ”, $part[6]));
$i++;
}
}
return $output;
}
}
[/php]

Auto-Establishing SSH Tunnels

Standard

SSH Tunnels – Auto-Establishing

I have a cron job which connects manually replicates a database over an SSH tunnel for those ‘Oh Sh!t’ moments. Sometimes that SSH tunnel will drop or fail to establish. Within the cron job I needed a way to make sure that didn’t happen.

The Code

The code below is the first part of the bash file executed by cron.

We run netstat -a and grep for the port the tunnel is supposed to be established on, and if it is less than 2, it will execute and create the tunnel.

[bash]
#!/bin/bash
REMOTEHOST=10.1.1.1
TUNNEL=$(netstat -a | grep -c 3307)

if [ $TUNNEL -lt 2 ]; then
ssh -f root@$REMOTEHOST -L 3307:localhost:3306 -N
fi
[/bash]

After the above snippet, you can continue whatever script or application which needed the SSH tunnel to be established.
Enjoy!

PHP FastCGI POST Requests Failing

Standard

The FastCGI Issue

I was working with a site that had to be migrated from a Virtual Dedicated Server to a GoDaddy 4GH plan and ran into an issue where POST forms passed through mod_rewrite were not being populated to $_POST.

I realized that in a FastCGI environment the requests will be redirected as a GET string, meaning that your POST data will be lost. It was a 1-liner in the ‘.htaccess’ file.

The Fix

If you have a R=301 in the brackets [], remove it so it looks like below:
[bash]
# On FastCGI replace the last line above with this:
RewriteRule ^(.*)$ index\.php?/$1 [L]
[/bash]

Enjoy.

Gotcha: WordPress Option Form Not Posting

Standard

The Issue – Form Not Posting

I was working on creating a theme with an Admin Options page for WordPress but ran into an issue from the article I was following where the form wouldn’t post. Normally, this is because there is either no action, or no interpreter for the _GET or _POST. Knowing this, I noticed there was no form action. Easy fix.

With WordPress, your actions are managed by your URI, example:
[plain]function.php?page=called.php[/plain]
When you bring that to different environments, not all servers will handle the request within the same $_SERVER variable. S

o what’s the best way to POST your form the page serving you?

The Fix

You can fix it by using a combination of substr and strrpos.

substr, or sub string, will allow you to return only the characters within the specified offsets. strrpos, or string reverse position, will return the first integer position of the character you specified, starting from the end of the string.

Understanding your URI, ex: http://www.highonphp.com/wordpress/wp-admin/admin.php?page=functions.php, you know that the page you need to post your form to is admin.php?page=functions.php.

So, by using the following function, we will get the position of the / after wp-admin/ and use that as the starting point for substr.

[php]
echo substr($_SERVER[‘REQUEST_URI’], strrpos($_SERVER[‘REQUEST_URI’], ‘/’)+1);
[/php]

When you put it all together the FORM tag looks like this:
[php]

PHP SSH2 Class with Exception Handling

Standard

SSH2 Wrapper Class

The following class takes some of the ideas used to create a contextual socket, and applied to the setup of a SSH2 stream. Currently, only password authentication is supported, but will be updated shortly. Support for SCP and SFTP will be included at a later time.

SSH2 Usage

[php]

$options = array(
‘host’ => ‘127.0.0.1’,
‘port’ => 22,
‘auth’ =>
array(
‘type’ => SSH2::PASS,
‘username’ => ‘user’,
‘password’ => ‘password’,
‘fingerprint’ => ‘xxxx’,
‘ssh_auth_pub’ => ‘3sg325235y43yre’,
‘ssh_auth_priv’ => ‘3sg325235y43yre’,
‘ssh_auth_priv_key’ => ‘3sg325235y43yre’,
)
);

try{
$ssh = new SSH2($options)->connect();
if($ssh->authenticate()){
/* For devices which support OpenSSH and OpenSSH2 Variants */
$exampleOutput = $ssh->exec(array(‘ls -lSha’, ‘cat ~/.bashrc’));

if(!$exampleOutput ){
echo $ssh->getLastError();
}else{
echo $exampleOutput ;
}

/* For devices which support net-sshd, vt100, etc */
$exampleOutput = $ssh->shell(array(‘ls -lSha’, ‘cat ~/.bashrc’));

if(!$exampleOutput ){
echo $ssh->getLastError();
}else{
echo $exampleOutput ;
}
}

$ssh->disconnect();
}
catch(SSH2FailedToConnectException $e){
print_r($e->getMessage());
}
catch(SSH2FailedToAuthenticate $e){
print_r($e->getMessage());
}
[/php]

Get The SSH2 Class

[php]
class SSH2{
private static $connection;
private $error;

var $port = 22;

const PASS = ‘password';
const PUBKEY = ‘publickey';

public function __construct(Array $options){
foreach($options as $opt => $value){
$this->$opt = $value;
}

return $this;
}

final function xdisconnect($reason, $message, $language) {
printf(“Server disconnected with reason code [%d] and message: %s\n”,
$reason, $message);
}

final function connect(){
$callbacks = array(‘disconnect’ => ‘xdisconnect’);

self::$connection = @ssh2_connect($this->host, $this->port, NULL, $callbacks);
if(self::$connection === FALSE){

throw new SSH2FailedToConnectException($this->host, $this->port);
return false;

}

$this->fingerprint = @ssh2_fingerprint(self::$connection);
return true;
}

// sm business
final function authenticate(){
$method = “ssh2_auth_{$this->auth[‘type’]}”;

if(@$method(self::$connection, $this->auth[‘username’], $this->auth[‘password’]) === FALSE){
throw new SSH2FailedToAuthenticate($this->host, $this->auth[‘username’], $this->auth[‘type’]);
return false;
}else{
return true;
}
}

public function exec($cmd){
if(is_array($cmd)){
foreach($cmd as $command){
$stream = @ssh2_exec(self::$connection, $command);
$errorStream = @ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);

/* Enable Blocking */
@stream_set_blocking($errorStream, true);
@stream_set_blocking($stream, true);

/* Grab Response */
$response .= stream_get_contents($stream);
$this->error .= stream_get_contents($errorStream);
}
}
else{
$stream = @ssh2_exec(self::$connection, $cmd);
$errorStream = @ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);

/* Enable Blocking */
@stream_set_blocking($errorStream, true);
@stream_set_blocking($stream, true);

/* Grab Response */
$response .= stream_get_contents($stream);
$this->error .= stream_get_contents($errorStream);
}

if(is_null($response)){
return false;
}

return $response;
}

final function shell($cmd){
$stream = ssh2_shell (self::$connection, ‘vt102′, null, 80, 40, SSH2_TERM_UNIT_CHARS);
$output = NULL;

if(is_array($cmd)){
foreach($cmd as $command){
fwrite($stream, $command.PHP_EOL);
sleep(2);

while(( $res = stream_get_contents($stream, -1)) !== false){
$output .= $res;
if($res == ”){
break;
}
}
}
}
else{
fwrite($stream, $cmd.PHP_EOL);
sleep(2);

while(( $res = stream_get_contents($stream, -1)) !== false){
$output .= $res;
if($res == ”){
break;
}
}

}

fwrite($stream, ‘exit’.PHP_EOL);

return $output;
}

public function disconnect(){
@ssh2_exec(self::$connection, ‘exit’);
}

public function getLastError(){
return $this->error;
}
}

/*
* Thrown if a class tries to access the XML parser’s functionality
*
* @author sixeightzero
* @license http://opensource.org/licenses/gpl-license.php GNU General Public Licence
* @copyright (c) 2011 – Mike Mackintosh
* @version 0.1
* @package Zepnik Framework
*/

final class SSH2FailedToConnectException extends Exception
{
/**
* Sets the error message
*
* @todo Add logger output
*/
public function __construct($host, $port)
{
$message = “Failed to connect to host ‘{$host}’ on port {$port}\n”;

// Call the parent constructor
parent::__construct($message);
}
}

final class SSH2FailedToAuthenticate extends Exception
{
/**
* Sets the error message
*
* @todo Add logger output
*/
public function __construct($host, $username, $type)
{
$message = “Failed to authenticate ‘{$username}’ by ‘{$type}’ on host ‘{$host}’\n”;

// Call the parent constructor
parent::__construct($message);
}
}
[/php]

jQuery: Creating A Hover Timeout

Standard

Creating a Hover Timeout

I came across the need to detect and delay a hover before executing a function. The page was full of images, and when hovered over, would create an AJAX request to the server and display in a popup.

Here is an example on how to achieve it.

[javascript]
$(‘img.expand’).bind({
mouseover: function() {
obj = $(this);

jQueryTimeout = setTimeout(function() {
$.post(‘/target-uri’,
{
‘attribute1′:obj.attr(‘title’),
‘attribute2′:obj.attr(‘href’)
},
function(response){
console.log(response);
},
‘json’
);
}, 2000);
},
mouseleave: function() {
clearTimeout(jQueryTimeout);
}
});
[/javascript]

Demo

In the demo, there is a link, ‘here’, and if you hover over it for 2 seconds, it will display the title attribute in the input text field below.

This is a demo. Hover here

Demo Code

[javascript]

[/javascript]

Fatal Error: Could not find ./bin/my_print_defaults

MySQL
Standard

Background

I was installing new servers in my lab for an application that’s about to be deployed. I was taking the normal steps which include MySQL, PHP and Apache which I have documented in the Web Server Basics article. While installing Percona, I ran across the following error:

[bash]
root@ubuntu:/home/splug/Percona-Server-5.5.17-rel22.1# /usr/local/mysql-5.5/bin/mysql_install_db

FATAL ERROR: Could not find ./bin/my_print_defaults

If you compiled from source, you need to run ‘make install’ to
copy the software into the correct location ready for operation.

If you are using a binary release, you must either be at the top
level of the extracted archive, or pass the –basedir option
pointing to that location.
[/bash]

The Fix

If you use my article, the MySQL page documents how to circumvent the issue. To get the location of your ‘my_print_defaults’ binary, use the ‘which’ command:

[bash]
# which my_print_defaults
/usr/local/mysql-5.5/bin/my_print_defaults
[/bash]

Then you can re-run the ‘mysql_install_db’ script passing the ‘–basedir’ option, leaving off the ‘/bin/my_print_defaults':

[bash]
root@ubuntu:/home/splug/Percona-Server-5.5.17-rel22.1# ./scripts/mysql_install_db –basedir=/usr/local/mysql-5.5 –user=mysql
Installing MySQL system tables…
120302 10:03:08 [Note] Flashcache bypass: disabled
120302 10:03:08 [Note] Flashcache setup error is : ioctl failed

OK
Filling help tables…
120302 10:03:09 [Note] Flashcache bypass: disabled
120302 10:03:09 [Note] Flashcache setup error is : ioctl failed

OK

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:

/usr/local/mysql-5.5/bin/mysqladmin -u root password ‘new-password’
/usr/local/mysql-5.5/bin/mysqladmin -u root -h ubuntu password ‘new-password’

Alternatively you can run:
/usr/local/mysql-5.5/bin/mysql_secure_installation

which will also give you the option of removing the test
databases and anonymous user created by default. This is
strongly recommended for production servers.

See the manual for more instructions.

You can start the MySQL daemon with:
cd /usr/local/mysql-5.5 ; /usr/local/mysql-5.5/bin/mysqld_safe &

You can test the MySQL daemon with mysql-test-run.pl
cd /usr/local/mysql-5.5/mysql-test ; perl mysql-test-run.pl

Please report any problems with the /usr/local/mysql-5.5/scripts/mysqlbug script!

Percona recommends that all production deployments be protected with a support
contract (http://www.percona.com/mysql-suppport/) to ensure the highest uptime,
be eligible for hot fixes, and boost your team’s productivity.
[/bash]

Hope this relieves someones headache.

Feature Creep: Battling A Developers Worst Enemey

Standard

What is Feature Creep?

Feature Creep is the delay of and applications deployment due to unnecessary features, additions, add-on’s and/or changes. Wikipedia even has an article on this:

Feature creep, creeping featurism or featureitis is the ongoing expansion or addition of new features in a product, such as in computer software.[1] Extra features go beyond the basic function of the product and so can result in over-complication rather than simple design. Viewed over a longer time period, extra or unnecessary features seem to creep into the system, beyond the initial goals.
Wikipedia

I started out programming as a hobbyist. I had multiple domains which ranged from a personal portfolio, a sandbox for development, a clan site for some games I used to play and others. The only time I actually finished a project was when I was on a deadline, with an extremely detailed workflow documented and agreed upon by the client.

Staying focused may sound easy but it is very difficult to achieve and it often leads to code fatigue. Code fatigue is where you spend an abundant amount of time writing source code leading to the burnout of the logical flow or thought process. Code fatigue is much like writers block. What many people don’t realize is that code fatigue leads to feature creep. A change of pace on your project is welcome when you are under a deadline, but that break in concentration can take you on a roller-coaster ride.

Here are some tips on how to flow with your application development life-cycle, from start to finish.

Know Your Audience

The first step of white-boarding a project is knowing your end-user. Understanding who is going to be the first exposed to your application or project is a very important step. If you are launching an application for developers to manage contacts and invoices, you don’t need to add a subnet calculator in its initial release. If you are designing an application for auditing network element configurations, you don’t need to add an extension for graphing your results in the first release; tabular data is sufficient.

Your users are the reason you are developing the app. They have a very specific need or want, and are requesting specific functionality. While working on the project, every time you get those, ‘Ah-hah!’ moments, write them down and save for later. They do not need to be included in your first launch, which cannot be stressed enough. Feature creep always starts out as a great idea, but ends up tormenting you.

Outline, Detail and Execute (ODE)

It pays off to wire frame and outline your app. One of the more common occurrences when feature creep occurs, is usually when there is no set-in-stone approach to developing. Some developers, such as myself, use this in a milestone based payment system. Applying a deadline to deliverables helps you stay on task.

I use the philosophy of Outline, Detail and Execute.

  • Outline - List what your goal is, list the steps needed to reach the goal, list all dependencies for each of those steps and a brief idea of how each step can be completed
  • Detail - Create a modifiable proof of concept for each step you created in the outline
  • Execute- Update your POC from the detail stage to support a development/production environment, framework, specific configuration

By staying disciplined in your work-flow you will ensure your focus is on what needs to be done, not what could be done.

Staying Focused

Feature Creep surfaces a lot of times when developers are fatigued with the instance they are currently working on. For example, bashing your head on the same 3 lines of code for 4 days can drive someone insane and kill off a whole bunch of brain cells. They start to think on how they can remedy the situation; they create an object or namespace as a remedy. They take that new focus and run with it for another three days unpronounced to them that the clock is still ticking.

Use this as a rule of thumb: every time you face palm, take a 10 minute walk across the web.

Use this as a rule of thumb: every time you face palm, take a 10 minute walk across the web.

Taking your focus off the issue, but keeping it on the specific instance of your project will help more than hurt. That quick break from thinking, will reduce code fatigue and give you a chance to regroup your thoughts subconsciously. If you are still suffering after coming back to the task, reach out for assistance. I can personally guarantee that almost every issue you run into, someone else has as well, and documented it.

Understanding Your Applications’ Flow

Keeping in mind your applications’ internal flow will help prevent feature creep. Remember, there is a reason we have code revisions outside the need for security patches and bug fixes. Not every feature you want needs to be in the first release. Although it would be nice, it is not necessary. There have been a few instances where projects were launched, and the feature overload factor came into play. Too many options, too many choices.

Check out this article from Smashing Magazine: Redefining Hicks Law. It goes a little more into detail about this subject. Here is another article from them as well, the easier the better.

Summary

Remember, Plan, Sketch, Do. Don’t get off track, don’t worry about the nooks and crannies. Don’t let feature creep creep it’s way into your daily routine. You can always go back and revise your code, launch it, and add feature sets. Not everything needs to be done at launch.

Enjoy.

PHP 5.4.0 Released!

php
Standard

What’s New In PHP 5.4.0?

The PHP Development Team would like to announce the immediate availability of PHP 5.4.0. This release is a major leap forward in the 5.x series, and includes a large number of new features and bug fixes.

Release Announcement: http://www.php.net/releases/5_4_0.php
Downloads: http://php.net/downloads.php#v5.4.0
ChangeLog: http://www.php.net/ChangeLog-5.php#5.4.0

Short Array Syntax

One of my favorite updates in 5.4 is the short array syntax. Being able to define an array with [] instead of array() is more of a cosmetic and ease of use update than a performance increase.
[php]
// as of PHP 5.4
$array = [
“foo” => “bar”,
“bar” => “foo”
];
[/php]