Wednesday, April 25, 2012

Installing Wordpress on CentOS 5.x

This is not the famous 5 minute installation, but it comes close. It takes other minor items into account, like php53 and the APC accelerator cache. I'll follow up soon with some backup scripts, but here's a baseline installation guide.

At the time of this blog entry, WordPress was up to version 3.3.2

Assumptions:
Server has a clean install of CentOS 5.x and access to the internet.

1. Login as root or su

2. Install Webserver and Database and other prerequisites
yum install httpd* mysqld* gcc* pcre-devel

3. Install php 5.3
http://noveckg.blogspot.com/2012/01/installing-php-53-on-centos-5x.html

4. Install a php accelerator
http://noveckg.blogspot.com/2012/01/installation-of-apc-on-php-53-centos-5x.html

5. Start services and configure to start on boot

chkconfig httpd on && service httpd start
chkconfig mysqld on && service mysqld start

6. Lock down mysql
/usr/bin/mysqladmin -u root password 'yourpasswordhere'
7. Create an empty wordpress database and account in Mysql
mysql -u root -p yourpasswordhere
At the mysql prompt:
CREATE DATABASE mydbname CHARSET 'utf8';
GRANT select,insert,update,delete,create,drop,index,alter
ON mydbname.*
TO mywpuser@localhost IDENTIFIED BY 'wpuserpassword';
flush privileges;
quit;

8. Download wordpress
cd /temp
wget http://wordpress.org/latest.zip
unzip latest.zip
cd wordpress
cp -r * /var/www/html/


9. Create a Wordpress data directory and assign permissions
cd /var/www/html/wp-content
mkdir uploads
mkdir cache
cd ../
chown –R apache:apache *

10. Copy default config file

cp wp-sample-config.php wp-config.php

11.    Edit config file
nano wp-config.php
Modify the following vars:
DB_NAME
The database name created in Step 7
DB_USER
The username created in Step 7
DB_PASSWORD
The password created in Step 7
DB_HOST
Localhost
(or specify remote host if applicable)

12. Open up a web browser to start WordPress config
http://my.server.ip/wp-admin/install.php

Press on..

-noveck

Thursday, April 12, 2012

Moodle: PHP script to convert Mysql database from MYISAM to InnoDB

I wrote (or rather modified an existing script) that batch converts the moodle database from MyISAM to InnoDB. This saves a lot of time, rather than writing a couple hundred ALTER TABLE statements, or even using the phpMyadmin interface.
Credit for the original script:
http://stackoverflow.com/questions/3856435/how-to-convert-all-tables-from-myisam-to-innodb
 
Please test on a copy of the database before using. Do not run on a production database! 
I can't emphasize that enough.

It's been tested on both Moodle 1.9 and 2.0/2/2, see script preamble for further details.

It's a potentially hazardous script, so I won't recommend placing it in any web accessible folders (like /var/www/html/..). It's been made relatively simple to implement, and the instructions are below:

0. Login as root/su

1. Ensure that InnoDB is enabled on your server
mysql -u root -p *****
SHOW ENGINES;
Expected output
...
InnoDB | YES | Supports transactions...


2. Install script on your server
Copy/Paste the code at the bottom of the post into a new file named innodb_convert.php on your Moodle server where the database is located.
Please ensure that it is not in a web accessible folder.



3. Give the file execute permissions to the script
chmod +x innodb_convert.php

4. Configuration
Open the file and navigate to the database configuration section (approx line 48). Set relevant variables.
$host = 'myhost'; //Specify host
$dbuser = 'myuser'; // Specify user with alter permissions 
$dbpass = 'mypass'; //user password
$mydb = 'mydb'; //specify schema or db to be modified
5. Save and exit.

6. From the command line, call the script using php
cd /tmp
php innodb_convert.php



7. Normal output expected:
ALTER TABLE mytable1 engine=InnodDB;
ALTER TABLE mytable2 engine=InnodDB;
ALTER TABLE mytablen engine=InnodDB;
Operation Completed

Confirm Storage Engine conversion using phpyadmin
or from Mysql: show create tablename.
Script Execution time: 999.99 seconds

The script (see preamble for additional information):

Download text file here.

<?php
// WARNING: PLEASE TEST BEFORE RUNNING ON A PRODUCTION DATABASE
// Tested on Moodle 1.9 and Moodle 2.0/2.2
//
// Disclaimer:
//
// This script was written to be executed from the command line in 
// Linux using a MYSQL database 
// and MYISAM storage engine. It converts the storage engine to 
// INNODB using the ALTER TABLE command.
//
// It assumes that the INNODB engine has been enabled. 
// This can be confirmed by logging into the mysql prompt 
// and running the command: 
// show engines;
//
// If it is disabled, check your my.cnf and 
// comment out the line: skip-innodb
//
// It does not check if disabled, so the script would execute 
 //and attempt to co
// It contains secure information, so DO NOT PLACE IN WEB DIRECTORY
//
// Execute from /temp and delete afterwards
//
// This is a modification of a script located here:
// http://stackoverflow.com/questions/3856435/how-to-convert-all-tables-from-myisam-to-innodb 
//
// Version : 1.2
// Date  : 11 April 2012
// Diff  :  check for recordset before executing alter table
//
// Version : 1.1
// Date  : 31 January 2012
// Diff  :  Added Timer to script; Display user and DB being affected
//
//
// Version :  1.0 
// Date  : 25 January 2012
//
// 
//
// Noveck Gowandan http://noveckg.blogspot.com

//Time Calculation - start count

$time = explode(' ',microtime());
$time = $time[1] + $time[0]; //return array
$begintime = $time; //define begin time

//Your database connection items here
 
$host = 'myhost'; //Specify host
$dbuser = 'myuser'; // Specify user with alter permissions 
$dbpass = 'mypass'; //user password
$mydb = 'mydb'; //specify schema or db to be modified


//connect to database using variables above
$link = mysql_connect($host,$dbuser,$dbpass);
$db = mysql_select_db($mydb);
   
if (!$link) {
die('Could not connect: ' . mysql_error());

}
echo "Connected Successfully to: $host." . "\n\n";
echo "Using database: $mydb." . "\n\n"; 
echo "Running script as $dbuser." . "\n\n";


//show tables in database
$sql = 'SHOW TABLES';
$rs = mysql_query($sql);

echo $sql;
echo "\n";

if (!$rs) {
die('SQL Recordset Error: ' . mysql_error());

}
else {
//loop through tables and convert to InnoDB
while($row = mysql_fetch_array($rs))
{
$tbl = $row[0];
$sql = "ALTER TABLE $tbl engine=InnoDB;";
mysql_query($sql);

echo $sql;
echo "\n";
}

echo 'Operation Completed.' . "\n\n";
echo 'Confirm Storage Engine conversion using phpmyadmin ' . "\n" . 'or from mysql: show create table tblname.' . "\n";

}
//close connection
mysql_close($link);

$time = explode(" ", microtime());
$time = $time[1] + $time[0]; 
$endtime = $time; //define end time
$totaltime = ($endtime - $begintime);
echo "Script Execution Time: $totaltime" . " seconds." . "\n\n";


?>

Thursday, March 15, 2012

Setting Up Master-Slave MySQL Replication on CentOS

I'm currently doing some research and testing into a MySQL Master-Slave setup on CentOS. It's a bit of a finicky setup and I had a couple stumbling blocks which may or may not happen to you. Just in case, these are documented further down the post.

No sense beating about the bush, let's jump right in...

First of all, this original guide was most helpful in my quest:


 Assumptions:
Base install of Centos completed.
IP of Mysql Master: 192.168.1.10
IP of Mysql Slave: 192.168.1.11
Default Mysql Path: /var/lib/mysql
Replication User: slave_user

On both Master and Slave:

0. Login as root or su


1. Install mysql packages
Yum install mysql*

2. Configure to start on boot
Chkconfig mysqld on

3. Start daemon and set relevant passwords
service mysqld start
--set root pw
mysqladmin –u root password “newpasswordgoeshere”

On Master:

1. Modify my.cnf

a)  remove comments or delete lines to enable networking and bind
#skip-networking
#bind-address = 127.0.0.1


b)    Designate server id
server-id = 1

c)    set an expiration date for the binlog
expire-logs-days=7

d)    Restart Mysql
service mysqld restart


2. Create Slave user and check Master Status.
Login to mysql as root and add a replication user account with associated privileges

GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'%' IDENTIFIED BY 'slave_password';
--for production environment, please specify IP’s or hostnames.
-- …TO 'slave_user'@'192.168.1._' …

FLUSH PRIVILEGES;
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;

Expected output
File        |Position|binlog_do_db|binlog_ignore_db
mysql-bin.001      | 500
!!Take note of the binfile and position, it is needed to start replication on the slave!

3.Backup database using preferred method and transfer to slave and restore.
In this instance, I used the innobackupex tool from percona xtrabackup (see blog post)

a) On the Master, Take the backup
innobackupex --defaults-file=/etc/my.cnf --user=***** --password=***** --databases=mydbname /path/to/backup/

b) SCP the backup files over the network to the slave
scp –r /path/to/backup/ user@server:/path/to/slave/destination**
**not mysql directory!!!



4. Unlock the tables.
Login to Mysql
UNLOCK TABLES;


On Slave:

1. Restore the backup

a) On the Slave, Prep the backup
innobackupex --apply-log --user=****** --password=****** /path /to/slave/destination

b) Restore the backup on slave
service mysqld stop
cp –r /path/to/slave/destination /var/lib/mysql
chown –R mysql:mysql *
chmod –R 771 *
service mysqld start


2. Configure Slave
a) open /etc/my.cnf and add under section [mysqld]
nano /etc/my.cnf
server-id=2
master-host=’192.168.1.10’
master-user=’slave_user’
master-password=’slave_password’
master-connect-retry=60
#Specify database to replicate
replicate-wild-do-table=mydb.%

relay log = /var/lib/mysql/mysql-relay-bin
relay-log-info-file = /var/lib/mysql/mysql-relay-log.info
relay-log-index = /var/lib/mysql/mysql-relay-bin.index
master-info-file = /var/lib/mysql/mysql-master.info


#more than likely this entry exists, however, it does not hurt to check
log-error = /var/log/mysqld.log
Save and exit.

b) Restart Mysql
service mysqld restart

3. Start Replication on Slave
a) Login to Mysqld and execute the following:

STOP SLAVE;
#For this next step, please confirm the binlog name and position from the SHOW MASTER STATUS command on the master, before the tables were unlocked!!
CHANGE MASTER TO MASTER_HOST='192.168.1.10', MASTER_USER='slave_user', MASTER_PASSWORD='slave-password', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.001', MASTER_LOG_POS=500;

START SLAVE;

b) To ensure that the slave is replicating, run the following command and take note of the following output:

SHOW SLAVE STATUS \G;
Expected output (snippet)
xxxxxxxxxx
Slave_IO_State: Waiting for master to send event


Slave_IO_Running: Yes
Slave_SQL_Running: Yes


Seconds_behind_master: 0
xxxxxxxxxx

4. Troubleshooting?
If the status is anything other than what is listed above, exit the mysql CLI and check the mysql log for troubleshooting.
cat /var/log/mysqld.log

5. Optional Issues and Fixes (may be specific to my test environment, so may not apply to all scenarios )
I encountered an issue in my test where the replication simply was not starting.
The output of the show slave status was as follows:
xxxxxxxxxx
Slave_IO_State:


Slave_IO_Running: No
Slave_SQL_Running: Yes


Seconds_behind_master: NULL
xxxxxxxxxx
Analysis of the mysqld log indicated:
Error 1236: Could not find first log file name in binary log index.
I followed the advice from this website and got it to work:
http://forums.mysql.com/read.php?26,9390,9390#msg-9390

STOP SLAVE;
FLUSH TABLES WITH READ LOCK;
UNLOCK TABLES;
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.001';
CHANGE MASTER TO MASTER_LOG_POS=500;
START SLAVE;



--End.

That was long. You deserve a cup of coffee.

Coming soon - Monitoring the replication and checking for replication errors. I'm still in the research phase here, so I'll update as soon as I can.

-noveck

Thursday, March 1, 2012

Find specific files then move them using a list [Linux]

In a previous post I mentioned finding and deleting certain files from Linux.
http://noveckg.blogspot.com/2011/01/find-and-delete-certain-files-in-centos.html

This time around, in order to maintain an audit trail and facilitate recovery options, a prudent approach would be to remove the files from the directory and place them somewhere else where disk util is not critical.

In this example, I used these scripts to clean up my MoodleData directory of old backup zipfiles. It saved tons of time so I didnt have to peruse over 8000 courses to clean this crap up. This may or may not apply to all moodle environments. Obviously, if you rely on this form of course backups, these scripts are not the solution for you. I'll reiterate what was said in that earlier post.


Basically what this command does is search a specified directory for a name/filetype and then move the files. 
If you run it from the top level directory (/), chances are something important may get moved and you can screw things up.

Command 1: Generate a list of backup zip files complete with filepath (datestamped for convenience). This can also be used as an index in case any files need to be replaced

find /path/to/moodledata/ -name \*backup\*.zip -exec ls -lh {} \; | awk '{ print $9}' > /path/to/course-backup-filelist-$(date +%Y-%m-%d).txt


 Command 2: read list line by line, and move file to alternative location

cat /path/to/course-backup-filelist-01-03-2012.txt | while read line; do mv "$line" /path/to/other/location; done


I managed to recover close to 20GB of storage from mostly unneeded files.

\m/ (rock on, moodlers)

-noveck



Monday, February 6, 2012

Testing Percona Xtrabackup (innobackupex)

My last post dealt with the installation of the Percona Xtrabackup tool for use on a Mysql innodb database.
After some tweaking and help from the Percona Docs, the following is a test backup, prep and restore of the full database (not incremental).

This assumes a test environment, so please don't try this on a running production environment. Before the database can be restored, the existing one will have to be renamed or moved. The options for this are straightforward. Stop the mysql daemon and make a binary copy of the files, or rename the source folder.

0. Login as root/su

1. Prerequisite configuration items

Configure datadir and in my.cnf and reboot mysqld service
nano /etc/my.cnf
 --find section
[mysqld]
--add line
datadir=/var/lib/mysql

service mysqld restart

2. Run full backup of specific database
innobackupex --defaults-file=/etc/my.cnf --user=***** --password=***** --databases=mydbname /path/to/backup/

3. Prepare backup files
innobackupex --apply-log --user=****** --password=****** /path /to/backup

4. Restore backup
service mysqld stop
cp –r /path/to/backup /var/lib/mysql
chown –R mysql:mysql /var/lib/mysql
chmod –R 771 /var/lib/mysql
service mysqld start

-n

Wednesday, February 1, 2012

Installing Percona xtrabackup on CentOS 5.x

This covers the basic installation of the xtrabackup package on CentOS. This is necessary in order to take hot backups of a database using the InnoDB storage engine. By default, Mysql has no options to take a full hot backup of a live InnoDB database.

For more information,  please see Percona's website located here: http://www.percona.com/doc/percona-xtrabackup/

0. Login as root

1. Get rpm from Percona
(check your server version before installing, there are specific RPM’s for 32-bit and 64-bit)
see here for rpm list: http://www.percona.com/downloads/percona-release/
cd /tmp
wget  http://www.percona.com/downloads/percona-release/percona-release-0.0-1.i386.rpm

2. Install rpm (32-bit on this test machine)
Rpm –Uvh percona-release-0.0-1.i386.rpm

3. Check repo for package
yum list | grep percona


4. Install xtrabackup
yum install xtrabackup --nogpgcheck
I still have testing to do on actual usage, so I'll create a new post on tests of backups and restoring databases.

-n

Tuesday, January 24, 2012

Installing Moodle 2.x on CentOS 5.7

This particular entry deals with installing (not migrating) a base Moodle 2.x installation on CentOS 5.7. A few non-standard packages were recommended at the time of writing this, so some sub-entries were made to document those steps separately.

This assumes the base installation of CentOS 5.7 has been completed and the server has connectivity to the web.

Login as root/su

Note: This installation does not default to an innodb database, As I'm a bit pressed for time at the moment, I'll either update this post, or create a new one on converting the database to innodb.



0. Update OS
yum update -y

1. Install Mysql5.5
See this post: http://noveckg.blogspot.com/2012/01/installation-of-mysql-55-on-centos-5x.html


2. Install Apache
yum install httpd*

3. Install php 5.3 
See this post: http://noveckg.blogspot.com/2012/01/installing-php-53-on-centos-5x.html

4. Install php accelerator (for performance)
See this post: http://noveckg.blogspot.com/2012/01/installation-of-apc-on-php-53-centos-5x.html



5. Download latest tarball and install into webroot
cd /temp
download moodle latest: http://download.moodle.org/download.php/stable22/moodle-latest-22.tgz
tar xzvf moodle-latest-22.tgz
cd moodle-latest-22.tgz
cp –r moodle/* /var/www/html/

6. Create empty database in MySQL

mysql -u root -p yourpasswordhere
At the mysql prompt:
CREATE DATABASE mydbname CHARSET 'utf8';
GRANT select,insert,update,delete,create,drop,index,alter
ON mydbname.*
TO mymoodleuser@localhost IDENTIFIED BY 'moodleuserpassword';
flush privileges;
quit;



7. Check web root permissions
cd /var/www/html
chown –R root:root *
chmod –R 755 *


8. Create MoodleData Folder (outside of web root)
mkdir /usr/moodledata
cd /usr/moodledata
chown -R apache:apache *
chmod –R 700 *


Note: Check here for security recommendations: http://docs.moodle.org/20/en/Security_recommendations

9. Setup Config.php
use instructions from here for a new installation: http://docs.moodle.org/21/en/RedHat_Linux_installation

10. Configure Apache to read from Moodle Data
nano /etc/httpd/conf/httpd.confAdd to end of file

[Directory "/usr/moodle/mymoodle"]*
DirectoryIndex index.php
AcceptPathInfo on
AllowOverride None
Options None
Order allow,deny
Allow from all

[/Directory]*
*substitute the [] with <> !!
11. Setup the Moodle Cron
nano /etc/crontab
add line
*/5 * * * * php /var/www/html/admin/cli/cron.php

12. Moodle!
Open up a web browser on the server and hit: http://localhost/admin
Install and configure as desired.


Happy Moodle-2-ing !

-noveck