Chris Hope's LAMP Blog - The Electric ToolboxChris Hope's LAMP Blog - The Electric Toolbox

Linux Apache MySQL and PHP articles by Chris Hope

This is Chris Hope's blog for Linux, Apache, MySQL and PHP (known as LAMP) and Javascript/jQuery. I started this website several years ago with articles about web programming, Linux and Windows tips and tricks, howtos etc.

The ten most recent articles can be found below in their entirety. Navigating the sections in the right navigation (under Categories) will bring up all the other posts, and you can also use the search box at the top of the page to find what you might be looking for.

Cast a Javascript variable as an integerCast a Javascript variable as an integer

Posted March 11th, 2015 in Javascript

If you attempt to add a numeric value to a string in Javascript, you'll end up with a string. If you get what appears to be a numeric value from a select option with Javascript, it's a string. To use a number that is cast as a string in Javascript as a number, first cast it to an integer with parseInt().

Use parseInt() to cast a string as an integer with Javascript

To ensure the value is an integer that you can do addition, subtraction, etc to, do this:

var x = parseInt(y);

If the number may have leading zeroes, pass the radix parameter to ensure the value is cast as base 10, otherwise it may be cast as an octal (or other) value:

var x = parseInt(y, 10);

As an example, if you're reading a value from a select with id "myselect" and need it to be a number, do this:

var ele = document.getElementById('myselect');
var x = parseInt(ele.options[ele.selectedIndex].value);

Change the passphrase for an SSH RSA key fileChange the passphrase for an SSH RSA key file

Posted March 6th, 2015 in Linux/Unix/BSD

Use the ssh-keygen command with the -p flag to change or remove the passphrase for an SSH RSA private key file.

Change or remove the passphrase

Run ssh-keygen with -p only will prompt you for the location of the keyfile (defaulting to ~/.ssh/id_rsa) the old passphrase and the new passphrase:

ssh-keygen -p

You will be prompted for the location of the file, which you can specify or hit <enter> to leave as the default:

Enter file in which the key is (/home/chris/.ssh/id_rsa):

Now enter the old passphrase, the new one and confirm it:

Enter old passphrase:
Enter new passphrase (empty for no passphrase): 
Enter same passphrase again:  Your identification has been saved with the new passphrase.

To remove the existing passphrase, simply hit <enter> at the steps where you enter the new one and then confirm it.

Other command line flags

You can also specify the path to the file when first calling ssh-keygen:

ssh-keygen -p -f /path/to/file

And even supply the old pass phrase and new ones of the command line, although I wouldn't recommend it unless you clear the bash session history afterwards:

ssh-keygen -p -f /path/to/file -P old_passphrase -N new_passphrase

To remove the passphrase without having to hit <enter> twice in the prompts, but have to type in the existing one so it's not visible on the command line:

ssh-keygen -p -N ""

You can of course optionally add the -f flag to this one too.

MySQL error can't open file - errno: 24MySQL error can't open file - errno: 24

Posted March 3rd, 2015 in MySql

After some maintenance was done to the virtual host server that one of my virtual servers was running on that required a host reboot, my websites weren't running due to the MySQL error "[ERROR] /usr/sbin/mysqld: Can't open file: './databasename/tablename.frm' (errno: 24)"


In my case, the issue was due to too many files being open. Increasing the open_files_limit setting and restarting MySQL fixed the issue. It's quite possible this error message will also occur for other reasons (e.g. file corruption), but in my case it was the file limit issue.

Longer answer

After working out it was not an issue with the web server (Nginx) or PHP, I checked the MySQL error log, which was full of messages like this (where "databasename" was the name of the database, and "tablename" was the name of the table):

[ERROR] /usr/sbin/mysqld: Can't open file: './databasename/tablename.frm' (errno: 24)

I was able to log into the MySQL command line and run a query against a database, and got the same sort of error message:

ERROR 1016 (HY000): Can't open file: './databasename/tablename.frm' (errno: 24)

After some Googling around, I found that the issue might be due to the open files limit setting not being high enough. You can check what the current setting is with this query, and result:

mysql> SHOW VARIABLES LIKE 'open_files_limit';
| Variable_name    | Value |
| open_files_limit | 1024  |
1 row in set (0.00 sec)

And then see how many files are currently open:

mysql> SHOW GLOBAL STATUS LIKE 'Open_files';
| Variable_name | Value |
| Open_files    | 712   |
1 row in set (0.01 sec)

Judging from the above result, I did actually have a high enough open files limit, but it was worth attempting to change the setting to see if it fixed the problem, seeing as the number of open files wasn't too far off the limit. I also found myself unable to subsequently open up a MySQL command prompt again.

Increasing the open_files_limit setting

The open_files_limit setting cannot be changed from the MySQL command line; it needs to be done in the configuration file and then MySQL restarted. Add the following line to the your my.cnf file:

open_files_limit = <your limit here>

Then restart MySQL.

In my case, it wouldn't shut down so after about 30 minutes I rebooted the server (it was reporting issues with open files again). When it came back up, the problem was gone, so increasing the open files limit solved my problem.

This is the error message in the log file when I was attempting to shut down MySQL, which confirms it was an issue with the file limit:

[ERROR] Error in accept: Too many open files

Grepping the error log now, I can see this particular message came up a number of times in the three hours the issue occurred for.

You can't set the open_files_limit dynamically

Note that you can't set open_files_limit dynamically from the MySQL command line; you have to change it in the configuration and restart.

If you run this:

mysql> SET GLOBAL open_files_limit = <your limit here>;

You will get this error message:

ERROR 1238 (HY000): Variable 'open_files_limit' is a read only variable

Add Feedly to Google Chrome's RSS Subscription ExtensionAdd Feedly to Google Chrome's RSS Subscription Extension

Posted February 21st, 2015 in Applications

If you have the RSS Subscription Extension (by Google) installed in Google Chrome, you can add additional services to the "subscribe to this feed using" drop down box. This post shows how to do this for Feedly.

Open up Chrome's preferences

Go to Chrome -> Preferences on a Mac, or hamburger/menu button -> Settings on Mac and other operating systems and click on the extensions option. Alternatively just type "chrome://extensions/" into the omnibar.

Chrome's menu, with settings option highlighted:

chrome's menu

Extensions option highlighted: 

select extensions

Adding Feedly as an option

Now scroll down your installed extensions until you find the RSS Subscription Extension (by Google) and click the "options" option:

find the rss extension

You'll see the ones that are installed, you can edit and remove existing ones and add a new one by clicking the "add" button, which is highlighted in the following screenshot:

adding a new subscription option

Now finally enter the description and URL:

adding feedly

You can make the description whatever you want it to be (but calling it "Feedly" makes sense), and put as the URL.

Now when clicking the RSS button in the omnibar, you'll be able to add it to Feedly. If you tick the "always use my default reader when subscribing to feeds" option, then whenever you click the RSS button you'll go straight into Feedly.

How to tell if Debian install is vulnerable to the GHOST exploitHow to tell if Debian install is vulnerable to the GHOST exploit

Posted January 29th, 2015 in Linux/Unix/BSD

The CVE-2015-0235 "GHOST" exploit exposes a buffer overflow in glibc gethostbyname. This post shows how you can tell if your Debian Squeeze or Lenny install is affected and how to patch it.

The CVE-2015-0235 exploit

Track the exploit and updates to Debian here at the Debian security tracker.

Squeeze / Debian 6 & Wheezy / Debian 7 are affected until updates are applied. There are security updates in place already, so you just need to update/upgrade your distro.

When eglibc is at version 2.11.3-4+deb6u4 or higher on Squeeze or 2.11.13-38+deb7u7 or higher on Wheezy, then you are OK and the exploit is patched. Note that you are looking for the "deb6u4" and "deb7u7" part. So the next version for Squeeze would be deb6u5, deb6u6 and so on.

How can I tell if my server is affected?

Run this from the command line:

ldd --version

Look at the first line for the eglibc version; the following example is from an unpatched Debian Squeeze server:

ldd (Debian EGLIBC 2.11.3-4+deb6u1) 2.11.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
Written by Roland McGrath and Ulrich Drepper.

Note that the version is 2.11.3-4+deb6u1, so it's affected.

How to update

Of course you'll regularly update your Debian servers so know how to do this already ;)

apt-get update
apt-get upgrade

You'll need to reboot your server after doing the updates, because of the reliance various services and applications have on glibc / eglibc.

What about Debian Lenny?

There do not appear to be any plans to patch Lenny, so you're out of luck for an easy update. There's some instructions here at serverfault about how to do a source patch to do it yourself.

Delete messages from the exim mail queueDelete messages from the exim mail queue

Posted November 12th, 2014 in Email Servers

This post shows how to delete a single message from the exim mail queue and also how to remove all of them using the exim command line tools.

Delete a single message from the exim mail queue

Use mailq / exim -bp to show the mail queue, e.g.:

$ mailq
 0m   528 1XoIxD-0001rc-8J 

And then run exim -Mrm [message id] to delete the specific message:

exim -Mrm 1XoIxD-0001rc-8J

If the message is successfully deleted, you'll see this:

Message 1XoIxD-0001rc-8J has been removed

If exim is currently processing the message, you'll see this and it won't be deleted:

Message 1XoIxD-0001rc-8J is locked

You either need to wait and try again later, or get the id of the process which is currently processing the message, kill it, and then run the command again (e.g. "ps ax 1XoIxD-0001rc-8J" and then "kill -9 [process id/s]). It's probably not recommended that you kill the process.

Delete all messages in the exim mail queue

Running "exiqgrep -i" returns all the message ids for queued emails; pipe that through "exim -Mrm" and all the messages will be deleted, with the same caveat as above: if exim is currently processing a message, that one will not be deleted so you need to try again later.

exiqgrep -i | xargs exim -Mrm

And the result, if one could be removed and another one couldn't:

Message 1XoJ1U-0001sC-ME has been removed
Message 1XoJ1i-0001sQ-UJ is locked

Change the hide extension flag from the command line on OS XChange the hide extension flag from the command line on OS X

Posted November 3rd, 2014 in OSX

There doesn't appear to be an easy way to change the "Hide extension" flag on multiple files on OS X - selecting "Get Info" on multiple files simply opens a window for every file selected... If you have XCode installed, it can easily be done from the command line with setfile.

Hide file extensions with setfile

Run this command to hide the file extensions for e.g. all PDF files in the current directory using Terminal:

setfile -a E *.pdf

Show file extensions with setfile

And this command shows the file extensions for PDF files:

setfile -a e *.pdf 

Another way?

Let me know in the comments section below if there's another / better way of doing this. The chflags command comes installed with OS X, but doesn't appear to have the ability to change the file extensions setting.

Use exim and exiqsumm to show mail queued by domainUse exim and exiqsumm to show mail queued by domain

Posted October 31st, 2014 in Email Servers

There are a number of exim commands to see what's in the mail queue etc; sometimes you need to be able to see what's in the queue by domain, to see where hold ups might be.

exim & exiqsumm

This command gets what's currently in the mail queue and then pipes it through exiqsumm to collate the data into a useful format, instead of outputting every single queued message:

exim -bp | exiqsumm

Either run it as root or using sudo. You may need to pass the full path to the exim and/or exiqsumm commands (e.g. sudo exim -bp | /usr/sbin/exiqsumm).


By domain, the output shows the number of messages, the total kb/mb of mail queued and the oldest and newest messages queued:

Count  Volume  Oldest  Newest  Domain
-----  ------  ------  ------  ------
   11   495KB     14h     14h
   20   900KB     14h     14h
  154  6930KB     14h     14h

If you are using exim for sending bulk email (email marketing), using this command can help to show if you have any issues sending to particular mail services/servers (e.g. Gmail, Yahoo, Hotmail, etc). Then use the logs / other exim output to work out what the issue is to help fix it.

Promo codes, discount vouchers, etcPromo codes, discount vouchers, etc

Posted October 29th, 2014 in Miscellaneous Postings (Updated December 2nd, 2014)

This post has promo codes and discount voucher codes that I come across that I find useful and may need in the near future.

Use the promo code CYBERGOOD at checkout for $8.99 .COM and .NET registrations and renewals, as well as 50% off a bunch of products. They'll be donating to Colorado Feeding Kids with every .COM and .NET registration. This is valid until December 5th 2014 at - the normal price is $10.99

From December 6th to 31st, you can still get a minimal discount, using JAZZERCISE to get .COM & .NET registrations and renewals for $10.25.

Convert StudlyCaps to words with PHPConvert StudlyCaps to words with PHP

Posted October 23rd, 2014 in PHP

I needed to convert a bunch of database fieldnames in PHP from StudlyCaps to regular words, preserving the capitalization of words (e.g. from StudlyCaps to Studly Caps), and found a useful function on StackOverflow.

The solution

I'm almost certainly going to need this function again in the future, hence posting it here on my blog as a bookmark. The solution, posted here at StackOverflow, looks like this:

function StudlyCapsToWords($StudlyCaps) {
    return implode(' ', preg_split('/(?<=[a-z])(?=[A-Z])|(?=[A-Z][a-z])/', $StudlyCaps, -1, PREG_SPLIT_NO_EMPTY));

Note that I've put the code into a function and changed the variable name from the original example.

This works even better than what I was after, because it preserves capitals that follow one another as a word, but then splits it on the next capital. Make sure you go to the StackOverflow page for a full description of how it works.

Some examples

echo StudlyCapsToWords('DatabaseFieldName');
echo StudlyCapsToWords('ThisIsATest');
echo StudlyCapsToWords('TextWithCAPSInIt');

The above examples output:
- Database Field Name
- This Is A Test
- Text With CAPS In It