A PHP Error was encountered

Severity: Warning

Message: ob_start(): output handler 'ob_gzhandler' cannot be used twice

Filename: libraries/Output.php

Line Number: 218

A PHP Error was encountered

Severity: Notice

Message: ob_start(): failed to create buffer

Filename: libraries/Output.php

Line Number: 218

Chris Hope's LAMP Blog - The Electric Toolbox

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.

Set PHP configuration options with NginxSet PHP configuration options with Nginx

Posted April 26th, 2015 in Nginx Web Server and PHP

There may be times you need to set specific PHP options for a virtualhost on Nginx, for example adding an automatically prepended file to all pages. This post shows how to do this.

PHP auto_prepend_file example with Nginx

Let's say you have a setting like this to make all .php files be parsed as PHP:

server {
  ... configuration options ...
  location ~ \.php$ {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_param	QUERY_STRING		$query_string;
    fastcgi_param	REQUEST_METHOD		$request_method;
    fastcgi_param	CONTENT_TYPE		$content_type;
    fastcgi_param	CONTENT_LENGTH		$content_length;
    ... etc etc ...
  }
}

Simply add this in with the other fastcgi_param values:

fastcgi_param PHP_VALUE auto_prepend_file=/path/to/prepend.php;

The above example will automatically prepend the file at /path/to/prepend.php to all files that have a .php extension and parse them as PHP.

You should be able to set any other PHP value that can be configured outside the php.ini file in the same way, changing auto_prepend_file to the confguration name, and /path/to/prepend.php to the configuration value.

Fix "access denied" error when parsing HTML as PHP with NginxFix "access denied" error when parsing HTML as PHP with Nginx

Posted April 25th, 2015 in Nginx Web Server and PHP

If you are attempting to get files with a .html extension parsed as PHP with Nginx + php-fpm, you might get an "access denied" error in your browser, and the error message "Access to the script '...' has been denied (see security.limit_extensions)" in your Nginx error log. This post shows how to allow html files to be parsed successfully as PHP with Nginx + php-fpm.

Nginx configuration block

Your Nginx configuration block will look something like this to parse HTM files as PHP:

server {
  ... configuration options ...
  location ~ \.html$ {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_param	QUERY_STRING		$query_string;
    fastcgi_param	REQUEST_METHOD		$request_method;
    fastcgi_param	CONTENT_TYPE		$content_type;
    fastcgi_param	CONTENT_LENGTH		$content_length;
    ... etc etc ...
  }
}

Error message

And yet when you access e.g. somefile.html you get "Access denied" in the browser.

You check the Nginx error log and see this:

2015/04/25 07:38:28 [error] 5942#0: *108814 FastCGI sent in stderr: "Access to the script '/path/to/somefile.html' has been denied (see security.limit_extensions)" while reading response header from upstream, client: 192.168.1.54, server: www.example.com, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "www.example.com"

The fix needed is suggested in the error message: "see security.limit_extensions"

Set security.limit_extensions

On Debian 7 Wheezy, the configuration file to edit this setting is at /etc/php5/fpm/pool.d/www.conf; on other distributions it may be in a different place.

Then search for security.limit_extensions. It should look something like this in the file by default:

; Limits the extensions of the main script FPM will allow to parse. This can
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; exectute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
;security.limit_extensions = .php .php3 .php4 .php5

If the security.limit_extensions has been set already, then add .html to it; if it hasn't then add it in with all the extensions you need to allow, e.g.:

security.limit_extensions = .php .html

Is it safe to do this?

When enabling this myself, my first thought was "Is this safe" and "Can a regular HTML file suddenly be parsed as PHP" and then obviously "Will this cause security issues with any WordPress blogs installed on my server?"

As far as I can tell, it shouldn't cause any issues, because you still have to allow .html files to be parsed through php-fpm in the Nginx config. If you haven't done that, then they won't.

If I am wrong, please add a comment below.

How to shrink a VMWare Fusion Linux virtual diskHow to shrink a VMWare Fusion Linux virtual disk

Posted April 21st, 2015 in OSX and VMWare

VMWare Fusion on Mac OSX allows you to shrink virtual disks easily for Windows virtual machines right from the graphical interface (Virtual Machine -> Settings -> General -> Clean Up Virtual Machine) but there isn't the same option to do this with Linux, so you need to do it from the command line.

1. Clean up space

First of all you should clean up whatever space you can on the Linux virtual machine by deleting uncessary files, etc. After doing that, run this command as the root user on the Linux VM to zero out any free space - if you don't do it, then the shrinking process won't reclaim any space:

cat /dev/zero > zero; sync; sleep 1; rm -f zero

You'll see this message when it has finished:

cat: write error: No space left on device

That's OK, because the idea was to fill the disk up and then delete the file afterwards.

2. Shut down the virtual machine

You can't reclaim space with the virtual machine running, so shut it down first.

3. Run the shrinking process

Open up Terminal on your Mac, change to the directory the virtual machine files are in (for example I have mine at ~/Virtual Machines/<vm name>) and then run the following commands, replacing "Virtual Disk.vmdk" with the actual name of your virtual disk image.

Note that if the filename contains spaces then the filename parameter to the command needs quotes around it, as in my examples.

The following examples assume VMWare Fusion is installed in Applications at the OSX disk root.

The first command defragments the disk:

/Applications/VMware\ Fusion.app/Contents/Library/vmware-vdiskmanager -d "Virtual Disk.vmdk"

I got the message "VixDiskLib: Invalid configuration file parameter. Failed to read configuration file." when running this command. I don't know what this error means, but the command worked successfully and this was the other output:

Defragment: 100% done.
Defragmentation completed successfully.

The second command then shrinks the disk:

/Applications/VMware\ Fusion.app/Contents/Library/vmware-vdiskmanager -k "Virtual Disk.vmdk"

Once again, I got the message "VixDiskLib: Invalid configuration file parameter. Failed to read configuration file." but again it all worked fine, and this was the output

Shrink: 100% done.
Shrink completed successfully.

I managed to reclaim 9GB of wasted space from doing this.

What is the virtual disk filename?

When you do a directory listing, you'll see a bunch of files and directories like this:

564d0102-8ca8-949e-169e-7f39e33745b7.vmem
564d13fe-4467-4a08-e14b-10c083090f70.vmem
564d13fe-4467-4a08-e14b-10c083090f70.vmem.lck/
Debian 7 64-bit-03868d7d.vmem
Debian 7 64-bit.nvram
Debian 7 64-bit.plist
Debian 7 64-bit.vmsd
Debian 7 64-bit.vmx*
Debian 7 64-bit.vmx.lck/
Debian 7 64-bit.vmxf
Virtual Disk-s001.vmdk
Virtual Disk-s002.vmdk
Virtual Disk-s003.vmdk
Virtual Disk-s004.vmdk
Virtual Disk-s005.vmdk
Virtual Disk-s006.vmdk
Virtual Disk-s007.vmdk
Virtual Disk-s008.vmdk
Virtual Disk-s009.vmdk
Virtual Disk-s010.vmdk
Virtual Disk-s011.vmdk
Virtual Disk.vmdk
Virtual Disk.vmdk.lck/
caches/
startMenu.plist
vmmcores-1.gz
vmmcores-2.gz
vmware-0.log
vmware-1.log
vmware-2.log
vmware.log

The disk images have the .vmdk file extension and in the above example have been split into 11 different files with numbered filenames. You don't need to defrag and shrink the numbered filenames, just the one without the numbers.

So in the above example, ignore Virtual Disk-s001.vmdk to Virtual Disk-s011.vmdk and run the command on Virtual Disk.vmdk.

If you do attempt to run the command on one of the numbered files, you'll get an error message like this one:

The file '/.../Virtual Disk-s001.vmdk' appears to be a sub-component of a virtual disk.
Did you mean '/.../Virtual Disk.vmdk'?
Failed to defragment: The specified file is not a virtual disk (0x3ebf).

Version used

I ran the above commands on VMWare Fusion 7.1.1 on OSX Yosemite 10.10.3.

Where are Vudu To Go downloaded movies stored on my Mac?Where are Vudu To Go downloaded movies stored on my Mac?

Posted April 19th, 2015 in Applications

The Vudu To Go app allows you to download movies you have purchased from Vudu* and stores them on your computer to watch using the app. But where are the files stored?

Location of Vudu To Go files on a Mac

The files are stored at /Users/<username>/Library/Preferences/com.vudu.air.Downloader\Local Store

When browsing for that location in Finder, click the "Go" file menu option and hold down the option key to show the "Library" option.

Then locate "Preferences"

Then "com.vudu.air.Downloader"

The "Local Store"

Under the local store you will find folders named with numbers. The media files are there.

Copying the files to another computer

It is possible to copy them to another computer in the same location. I attempted to copy the entire com.vudu.air.Downloader folder but it kept crashing on the other computer.

So I deleted it and ran the app again, started downloading the movie, shut down the app, copied the movie directory over and it worked fine. You probably don't need to go through the "start download and stop the app" step and can probably just copy the movie directory over, just probably don't mess with the files in the root level of that folder.

Can you control where they are saved?

No, but it might be possible to symlink the directory location to somewhere else, e.g. an external hard drive, but I haven't tried this myself.

Can you download rented movies too?

* I noted at the start that Vudu 2 Go lets you download movies you purchased with Vudu, but possibly it can let you download the ones you've rented to. I'm not sure about this, either way.

Tools for setting up and testing secure certificatesTools for setting up and testing secure certificates

Posted April 18th, 2015 in Linux/Unix/BSD

This is a quick reference page for some tools for configuring web server settings and testing secure certificates.

Mozilla SSL Configuration Generator

This tool provides you with SSL configurations for Apache, Nginx, HAProxy & AWS Elb, depending on the server version and openssl version.

https://mozilla.github.io/server-side-tls/ssl-config-generator/

To find out your openssl version, do this:

openssl version

To find out your Apache version, do this (depending on distro it'll be apache2 or httpd, and you may need to prefix it with /usr/sbin):

apache2 -v
OR
httpd -v

To find out your Nginx version, do this (again you might need to prefix with /usr/sbin):

nginx -v

Qualys SSL Labs SSL Server Test

This tool tests your secure certificate and gives it a grade. On a couple of older servers, I was able to improve the grade from an "F" to a "B" simply by using the Mozilla SSL configuration generator above. We should be able to get them to an "A" by fixing the intermediate certificate when we renew.

https://www.ssllabs.com/ssltest/

[Update] I bought a new certificate for a site using RapidSSL, the Mozilla configuration generator and with up to date Nginx & openssl on Debian 7 Wheezy and got an A+ with the testing tool.

Screen: cannot open your terminal '/dev/pts/0'Screen: cannot open your terminal '/dev/pts/0'

Posted April 17th, 2015 in Linux/Unix/BSD

If you are logged in as a user using "su" or "sudo su" and attempt to use screen, you'll get the error message "Cannot open your terminal '/dev/pts/0' - please check". This post shows how to fix this.

Solution 1

Log out of the terminal/SSH session and log back in as the user you want to run screen as instead of using su.

Solution 2

script /dev/null
screen

Reference

http://serverfault.com/questions/116775/sudo-as-different-user-and-running-screen/116830

This worked for me on Debian 7.8 Wheezy.

MySQL: order a string column as an integerMySQL: order a string column as an integer

Posted April 16th, 2015 in MySql

If you order a string column that contains only numeric values with MySQL, it will order them as string values, e.g.: 1, 10, 100, 2, 3, 31, 32, 4, etc. If you want to order them as if they were an integer, cast them in the order by clause.

tl;dr

SELECT * FROM <table> ORDER BY CAST(<column> AS unsigned)

Why?

Normally you'd store numeric values in a numeric column in the database, but sometimes this isn't possible. For example, the postmeta table in WordPress has a meta_value column which is a string and in which you might store only numeric values for a particular meta_key field.

When the values are strings, they are sorted as strings, so 1, 2, 3, 4, 10, 31, 32, 100 would be sorted as 1, 10, 100, 2, 3, 31, 32, 4 as shown in the example in the first paragraph.

Casting the value as "unsigned" or "signed" in the sort part of the query will instead sort the value as an integer and give the desired result, assuming all the values are indeed numeric.

Speed impact?

I haven't measure this myself, but there will be an obvious impact in speed, especially if the resultset is large. However, it may be fairly minimal and depending on what you are using this query for, it may not matter.

A couple of WordPress examples

Using WordPress as an example, here's a query on the wp_postmeta table finding records with a meta_key of _ct_text_552c8612842c1, which was created using CustomPress, and then ordering them numerically:

SELECT * FROM wp_postmeta
WHERE pm.meta_key = '_ct_text_552c8612842c1'
ORDER BY CAST(pm.meta_value as unsigned)

In my case, I needed to join this to all posts of type 'forum', and here's another example:

SELECT p.ID, pm.meta_value
FROM wp_posts p
INNER JOIN wp_postmeta pm ON pm.post_id = p.ID
WHERE p.post_type = 'forum'
AND p.post_status = 'publish'
AND pm.meta_key = '_ct_text_552c8612842c1'
AND pm.meta_value != ''
ORDER BY CAST(pm.meta_value as unsigned)

That's all for now, I hope you found this useful!

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)"

tl;dr

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