Intro
I’m changing servers from Ubuntu server to CentOS. On Ubuntu I just checked off LAMP and got my environment. In CentOS I’m doing it piece-by-piece. I don’t think my Ubuntu install is quite regular, either, as I bastardized it by adding environment variables in the Apache config file, a concept I borrowed from SLES! Turns out it is quite an ordeal to make a smooth transition. I will share all my pitfalls. I still don’t have it working, but I think I’m over the hump. [Update: now it is working, or 99% of it is working. It is a bit sluggish, however.]
The Details
I installed httpd on CentOS using yum. I also installed some php5 packages which I saw were recommended as well. First thing I noticed is that the directory structure for “httpd” as it seems to be known on CentOS, is dramatically different from “apache2” as it is known in Ubuntu. This example illustrates the point. In CentOS the main config file is
/etc/httpd/conf/httpd.conf
while in Ubuntu I had
/etc/apache2/apache2.conf
so I tarred up my /etc/apache2 files and had the thought “Let’s make this work on CentOS.” Ha. Easier said than done.
To remind, the content of /etc/apache2 is:
apache2.conf, conf.d, sites-enabled sites-available mods-enabled mods-available plus some stuff I probably added, including envvars, httpd.conf and ports.conf.
envvars contains environment variables which are subsequently referenced in the config files, like these:
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
export APACHE_PID_FILE=/var/run/apache2$SUFFIX.pid
export APACHE_RUN_DIR=/var/run/apache2$SUFFIX
export APACHE_LOCK_DIR=/var/lock/apache2$SUFFIX
# Only /var/log/apache2 is handled by /etc/logrotate.d/apache2.
export APACHE_LOG_DIR=/var/log/apache2$SUFFIX |
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
export APACHE_PID_FILE=/var/run/apache2$SUFFIX.pid
export APACHE_RUN_DIR=/var/run/apache2$SUFFIX
export APACHE_LOCK_DIR=/var/lock/apache2$SUFFIX
# Only /var/log/apache2 is handled by /etc/logrotate.d/apache2.
export APACHE_LOG_DIR=/var/log/apache2$SUFFIX
First step? Well we have to hook httpd startup to our new directory somehow. I don’t recall this part so well. I think I tried this from the command line:
$ apachectl -d /etc/apache2 -f apache2.conf -k start
and it may be at that point that I got the MPM workers error. But I forget. I switched to using the service command and that particular error seemed to go away at some point. I don’t believe I needed to do anything special.
So I tried this edit to /etc/sysconfig/httpd (sparing you the failed attempts):
OPTIONS=”-d /etc/apache2 -f apache2.conf”
Now we try to launch and see what happens.
$ service httpd start
Starting httpd: httpd: Syntax error on line 203 of /etc/apache2/apache2.conf: Syntax error on line 1 of /etc/apache2/mods-enabled/alias.load: Cannot load /usr/lib/apache2/modules/mod_alias.so into server: /usr/lib/apache2/modules/mod_alias.so: cannot open shared object file: No such file or directory
[FAILED] |
Starting httpd: httpd: Syntax error on line 203 of /etc/apache2/apache2.conf: Syntax error on line 1 of /etc/apache2/mods-enabled/alias.load: Cannot load /usr/lib/apache2/modules/mod_alias.so into server: /usr/lib/apache2/modules/mod_alias.so: cannot open shared object file: No such file or directory
[FAILED]
Fasten your seatbelts, put on your big-boy pants or whatever. We’re just getting warmed up.
Let’s look at mods-available/alias.load:
$ more alias.load
LoadModule alias_module /usr/lib/apache2/modules/mod_alias.so |
LoadModule alias_module /usr/lib/apache2/modules/mod_alias.so
Sure enough, there is not only no such file, there is not even such a directory as /usr/lib/apache2. And all the load files have references like that. Where did the httpd install put its modules anyways? Why in /etc/httpd/modules. So I made a command decision:
$ mkdir /usr/lib/apache2
$ cd !$
$ ln -s /etc/httpd/modules
So where does that put us? Here:
$ service httpd start
Starting httpd: httpd: Syntax error on line 203 of /etc/apache2/apache2.conf: Syntax error on line 1 of /etc/apache2/mods-enabled/ssl.load: Cannot load /usr/lib/apache2/modules/mod_ssl.so into server: /usr/lib/apache2/modules/mod_ssl.so: cannot open shared object file: No such file or directory
[FAILED] |
Starting httpd: httpd: Syntax error on line 203 of /etc/apache2/apache2.conf: Syntax error on line 1 of /etc/apache2/mods-enabled/ssl.load: Cannot load /usr/lib/apache2/modules/mod_ssl.so into server: /usr/lib/apache2/modules/mod_ssl.so: cannot open shared object file: No such file or directory
[FAILED]
Not everyone will see this issue. I had used SSL for some testing in Ubuntu so I had that module enabled. my CentOS is a core image and did not come with an SSL module. So let’s get it.
$ yum search mod_ssl
shows the full module name to be mod_ssl.x86_64, so we install it with yum install.
How far did that get us? To here:
$ service httpd start
Starting httpd: httpd: bad user name ${APACHE_RUN_USER}
[FAILED] |
Starting httpd: httpd: bad user name ${APACHE_RUN_USER}
[FAILED]
Ah, remember my environment variables from above? As I said I actually use them with lines such as:
User ${APACHE_RUN_USER}
in apache2.conf. But clearly the definitions of those environment variables is not getting passed along. I decide to see if this step might work. I append these two lines to /etc/sysconfig/httpd:
$ Read in our environment variables. Inspired by apache on SLES.
. /etc/apache2/envvars |
$ Read in our environment variables. Inspired by apache on SLES.
. /etc/apache2/envvars
Could any more go wrong? Sure. Lots! Then there’s this:
$ service httpd start
Starting httpd: httpd: bad user name www-data
[FAILED] |
Starting httpd: httpd: bad user name www-data
[FAILED]
Amongst all the other stark differences, ubuntu and CentOS use different users to run apache. Great! So I create a www-data user as userid 33, gid 33 because that’s how it was under ubuntu. but GID 33 is already taken in CentOS. It is backup. I decide I will never use it that way, and change the group name to www-data.
That brings us here. you see I have a lot of patience…
$ service httpd start
Starting httpd: Syntax error on line 218 of /etc/apache2/apache2.conf:
Invalid command 'LogFormat', perhaps misspelled or defined by a module not included in the server configuration
[FAILED] |
Starting httpd: Syntax error on line 218 of /etc/apache2/apache2.conf:
Invalid command 'LogFormat', perhaps misspelled or defined by a module not included in the server configuration
[FAILED]
Now my line 218 looks pretty regular. It’s simply:
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined |
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
I then realized something interesting. The modules built in to httpd on centOS and apache2 are different. apache2 seems to have some modules built in for logging:
$ apache2 -l
Compiled in modules:
core.c
mod_log_config.c
mod_logio.c
prefork.c
http_core.c
mod_so.c |
Compiled in modules:
core.c
mod_log_config.c
mod_logio.c
prefork.c
http_core.c
mod_so.c
whereas httpd does not:
$ httpd -l
Compiled in modules:
core.c
prefork.c
http_core.c
mod_so.c |
Compiled in modules:
core.c
prefork.c
http_core.c
mod_so.c
So I made an empty log_config.conf and a log_config.load in mods-available that reads:
LoadModule log_config_module /usr/lib/apache2/modules/mod_log_config.so |
LoadModule log_config_module /usr/lib/apache2/modules/mod_log_config.so
I got the correct names by looking at the apache web site documenttion on that module. And i linked those two files up in the mods-available diretory:
$ cd mods-enabled
$ ln -s ../mods-available/log_config.conf
$ ln -s ../mods-available/log_config.load
Next error, please! Certainly. It is:
$ service httpd start
Starting httpd: Syntax error on line 218 of /etc/apache2/apache2.conf:
Unrecognized LogFormat directive %O
[FAILED] |
Starting httpd: Syntax error on line 218 of /etc/apache2/apache2.conf:
Unrecognized LogFormat directive %O
[FAILED]
where line 218 is as recorded above. Well, some searches showed that you need the logio module. Note that it is also compiled into to apache2, but missing from httpd. So I did a similar thing with defining the necessary mods-{available,enabled} files. logio.load reads:
LoadModule logio_module /usr/lib/apache2/modules/mod_logio.so |
LoadModule logio_module /usr/lib/apache2/modules/mod_logio.so
The next?
$ service httpd start
Starting httpd: (2)No such file or directory: httpd: could not open error log file /var/log/apache2/error.log.
Unable to open logs
[FAILED] |
Starting httpd: (2)No such file or directory: httpd: could not open error log file /var/log/apache2/error.log.
Unable to open logs
[FAILED]
Oops. Didn’t make that directory. Naturally httpd and apache2 use different directories for logging. What else could you expect?
Now we’re down to this minimalist error:
$ service httpd start
Starting httpd: [FAILED]
The error log contained this line:
[Mon Mar 19 14:11:14 2012] [error] (2)No such file or directory: Cannot create SSLMutex with file `/var/run/apache2/ssl_mutex' |
[Mon Mar 19 14:11:14 2012] [error] (2)No such file or directory: Cannot create SSLMutex with file `/var/run/apache2/ssl_mutex'
After puzzling some over this what I eventually noticed is that my environment has references to directories which I haven’t defined yet:
export APACHE_RUN_DIR=/var/run/apache2$SUFFIX
export APACHE_LOCK_DIR=/var/lock/apache2$SUFFIX |
export APACHE_RUN_DIR=/var/run/apache2$SUFFIX
export APACHE_LOCK_DIR=/var/lock/apache2$SUFFIX
So I created them.
And now I get:
$ service httpd start
Starting httpd: [ OK ]
But all is still not well. I cannot stop it the proper way. Trying to read its status goes like this:
$ service httpd status
httpd dead but subsys locked
I looked this one up. Killed off processes and semaphores as recommended with ipcs -s (see this link), etc. But since my case is different, I also did something different. I modified my /etc/init.d/httpd file:
#pidfile=${PIDFILE-/var/run/httpd/httpd.pid}
pidfile=${PIDFILE-/var/run/apache2.pid}
#lockfile=${LOCKFILE-/var/lock/subsys/httpd}
lockfile=${LOCKFILE-/var/lock/subsys/apache2} |
#pidfile=${PIDFILE-/var/run/httpd/httpd.pid}
pidfile=${PIDFILE-/var/run/apache2.pid}
#lockfile=${LOCKFILE-/var/lock/subsys/httpd}
lockfile=${LOCKFILE-/var/lock/subsys/apache2}
Believe it or not, this worked. I can now run service httpd status and service httpd stop. To prove it:
$ service httpd status
httpd (pid 30366) is running...
Another Error Crops Up
I eventually noticed another problem with the web site. My trajectory page was not working. Upon investigation I found this comment in my main apache error log (not my virtual server error log, which I still don’t understand):
sh: /home/drj/traj/traj4.pl: Permission denied |
sh: /home/drj/traj/traj4.pl: Permission denied
This had to be a result of my call-out to a perl program from a php program:
...
$data = exec('/home/drj/traj/traj4.pl'.' '.$escargs);
... |
...
$data = exec('/home/drj/traj/traj4.pl'.' '.$escargs);
...
But what’s so special about that call? Worked fine on Ubuntu, and I did a directory listing to show the file was really there. Well, here’s the thing, that file is under my home directory and guess what? When you crate your users in Ubuntu the home directory permissions are set to group and others read. Not in CentOS! A listing of /home looks kind of like this:
/home$ ll
total 12
drwx------ 2 drj drj 4096 Mar 19 15:26 drj/
...
I set the permissions for all to read:
$ sudo chmod g+rx,o+rx drj
and I was good to go. The program began to work.
May 2013 Update
I was asked how all this survived after a yum update. Answer: pretty well, but not perfectly. The daemon was fine. And what miseld me is that it started fine. But then a couple days later I was looking at my access log and realized…it wasn’t there! Nor the errors log. Well, actually, the default access and error logs were there, but not for my virtual servers.
I soon realized that
$ service httpd status
produced
httpd dead but subsys locked
Well, who reads or remembers their own posts from a year ago? I totally forgot I had already dealt with this once, and my own post didn’t show up in my DDG search. Anywho, I stepped on the same rake twice. Being less patient this time around, probably because I am one year older, I simply altered the /etc/init.d/httpd file (looks like it had been changed by the update) thusly:
#pidfile=${PIDFILE-/var/run/httpd/httpd.pid}
#lockfile=${LOCKFILE-/var/lock/subsys/httpd}
# try as an experiment - DrJ 5/3/13
pidfile=/var/run/apache2.pid
lockfile=/var/lock/apache2/accept.lock |
#pidfile=${PIDFILE-/var/run/httpd/httpd.pid}
#lockfile=${LOCKFILE-/var/lock/subsys/httpd}
# try as an experiment - DrJ 5/3/13
pidfile=/var/run/apache2.pid
lockfile=/var/lock/apache2/accept.lock
and I made sure I had a /var/lock/apache2 directory. This worked.
I chose a lock file with that particular name because I noticed this in my /etc/apache2/apache2.conf:
LockFile ${APACHE_LOCK_DIR}/accept.lock |
LockFile ${APACHE_LOCK_DIR}/accept.lock
To clean things out as I was working and re-working this problem since I couldn’t run
$ service httpd stop
I ran instead:
$ pkill -9 -f sbin/httpd
and I removed /var/run/apache2.pid.
Now, once again, I can get a status on my httpd service and restart works as well and my access and error logs are being written.
Conclusion
This conversion exercise turned out to be quite a teaching lesson and even after all this more remains. After the mysql migration I find the performance to be sub-par – about twice as slow as it was on Ubuntu.
Four months later, CentOS has not crashed once on me. Contrast that with Ubuntu freezing every two weeks or so. I optimized MySQL to cache some data and performance is adequate. I also have since learned about bitnami, which is kind of a stack for all the stuff I was using. Check out bitnami.org.