SEARCH
LATEST NEWS
Some pages including homepage still need to be migrated to the new layout, this should be finished soon. If something doesn't work properly, let me know, please.
21/07/2012
All pages are about to be revised and updated if necessary. New content will be added - this includes new Apache-related articles, Oracle-related tips, several online tools.
14/07/2012
I'm working on a new release (2.0.2) of Cross-Linker plugin for WordPress, more information to be found on the official page of Cross-Linker: /make-donation-cross-linker-plugin-wordpress.html.
14/07/2012
PHP eaccelerator Causes CPU Overload (and Perhaps Indefinite Loops in Apache)
The Problem
I installed PHP accelerator called eaccelerator on my server in order to make PHP scripts run faster. One disadvantage of PHP is that each time a PHP page is called, it's going to be compiled entirely no matter it was compiled 1 or 2 seconds ago. Even in the same second there may be several http requests causing some script to be compiled again and again. Surely, a website with a script that can be executed in less than 0.05 seconds, and with not more than several hundreds of daily visitors, doesn't need any PHP scripts acceleration. But the reality is like this; Visitors visit your website, googlebot crawls it, spam bots do it too. So even your website isn't getting enough human visitors, bots can cause too many http requests which naturally result in plenty of scripts executions (and thus compilations too!).
The Solution
Installing eaccelerator is quite easy. Suppose that you have full root access to your server, it is very easy (there are other websites explaining how to install eaccelerator). However, after I installed the thing, it took about 2 weeks until the first problem occurred. For no apparent reason Apache stopped serving scripts, CPU load was over 250 (1 = 100%, so 250 = 25000%) and I had to restart the Apache. The configuration of eaccelerator wasn't modified that time. So I thought it's the lack of RAM which caused the problem. OK, I paid for another 1GB of RAM and also increased memory for eaccelerator (see configuration to do it, this article is about something else) from 32MB to 128MB. Things were running smoothly for another week or so. After this another CPU overload happened. Please, note that I haven't had any such a problem for almost 2 years - without eaccelerator. So I decided to setup a cron job to restart Apache web server occasionally (once a week). After a couple of days another CPU overload. So let the Apache server restart each day. Anyway, after configuring this cron job, another failure happened and my server wasn't serving scripts for over 9 hours. I am not sure what is causing the problem as I am not an eaccelerator coder, but looks like there is some indefinite loop.Time to change something!
Disadvantages of Restarting the Apache Web Server, Task Definition and Options
Restarting the Apache Web Server is what I don't want the most because simply when it's restarted, all cached scripts are lost and they have to be executed once again to be stored in cache again. In the end it's losing performance, time and wasting hardware resources. Another option would be disabling eaccelerator, but this would be just a return to the original problem. So the task was: "Restart the Apache server only when something went wrong". Here were the options:
- Setup a cron job to restart Apache every hour (not good, eaccelerator's effect would be minimal) - This isn't actually one of the options
- Create a script that would check CPU load and if it's too high then restart Apache
- Create a script that would make a http request to some known URL on the server to check if the page loads in an expected time internal and restart the Apache server if there is a timeout
- Create a script that runs in background on my own machine and downloads some URL's content - and again, if there is a timeout, warn me
The Solution
Simple fact: These scripts must be written in C, not in PHP. Simply because you cannot call a PHP script if Apache isn't working. Here below are all scripts that I'm using to avoid eaccelerator from overloading CPU. The article continues below.
Check CPU Overload Script
This script runs the uptime command and looks for ge: from load average: . Once it's found, the decimal number after this string is extracted and put into vysledok variable. If it's higher than 5, which means CPU load 500%, Apache is being restarted. Just make sure you're using own paths and filenames.
#include <stdio.h>
#include <stdlib.h>
int desat(int val)
{
int ret_val = 10;
int z;
for(z=1;z<val;z++)
ret_val = 10 * ret_val;
if(val==0)
ret_val = 1;
if(val==1)
ret_val = 10;
return(ret_val);
}
int main(void)
{
int cntr;
FILE *pipe_fp;
FILE * pFile;
int c,i;
int n = 0;
int ccomp[4]={0,0,0,0};
int cchar = 0;
int start = 0;
int track[10];
int counter = 0;
int vysledok = 0;
/* Create one way pipe line with call to popen() */
if (( pipe_fp = popen("/sbin/logsave /home/aquafishnet/crons/out.text uptime", "w")) == NULL)
{
perror("popen");
exit(1);
}
/* Close the pipe */
pclose(pipe_fp);
pFile=fopen ("/home/aquafishnet/crons/out.text","r");
if (pFile==NULL) perror ("Error opening file");
else
{
do
{
c = fgetc (pFile);
if(start==1)
{
if((c>=48)&&(c<=57))
{
counter++;
track[counter] = c-48;
}
else
{
start = 0;
}
}
for(i=2;i<=4;i++)
ccomp[(i-1)] = ccomp[i];
ccomp[4] = c;
if((ccomp[1]==103)&&(ccomp[2]==101)&&(ccomp[3]==58)&&(ccomp[4]==32))
start = 1;
}
while (c != EOF);
fclose (pFile);
}
// printf("\n load:");
for(i=counter;i>=1;i--)
vysledok = vysledok + (track[i]*desat((counter-i)));
if(vysledok>5)
{
if (( pipe_fp = popen("/sbin/logsave /home/aquafishnet/crons/out_restart.text /etc/rc.d/init.d/httpd restart", "w")) == NULL)
{
perror("popen");
exit(2);
}
/* Close the pipe */
pclose(pipe_fp);
}
return(0);
}
Check HTTP Response Script
This scripts calls the wget function and tries to download content from http://10.0.0.1/myfile.php. If response tooks longer than 9 seconds, let's restart Apache. If the previous script fails when detecting CPU load, this script will ensure that Apache is restarted when something's wrong. Again, make sure that you modify the paths to make this script work properly.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main ()
{
FILE *pipe_fp;
time_t seconds0, seconds1;
int vysledok;
seconds0 = time (NULL);
/* Create one way pipe line with call to popen() */
if (( pipe_fp = popen("/sbin/logsave /home/aquafishnet/crons/out_self.text wget http://10.0.0.1/myfile.php --delete-after --timeout=10 --tries=1", "w")) == NULL)
{
perror("popen");
exit(1);
}
/* Close the pipe */
pclose(pipe_fp);
seconds1 = time (NULL);
// printf ("1: %d \n", seconds0);
// printf ("2: %d \n", seconds1);
vysledok = seconds1 - seconds0;
if(vysledok>9)
{
if (( pipe_fp = popen("/sbin/logsave /home/aquafishnet/crons/out_restart.text /etc/rc.d/init.d/httpd restart", "w")) == NULL)
{
perror("popen");
exit(2);
}
/* Close the pipe */
pclose(pipe_fp);
}
// printf("%d",vysledok);
return 0;
}
Run Alarm on Your Own Machine if Website is Unreachable
This script runs on my local computer and starts playing alarm sound when the site is unreachable. Firstly we check for google availability, which I suppose is 100% available. If it's not available, there may be a problem in your internet connection and the script doesn't try to download content of your website. If HTTP request from Google is OK, then let's check your own website too. If the time required for downloading a page exceeds 9 seconds, the alarm sound is played via smplayer.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main ()
{
FILE *pipe_fp;
time_t seconds0, seconds1;
int vysledok;
int vysledokn;
while(1==1)
{
seconds0 = time (NULL);
if (( pipe_fp = popen("wget http://www.google.com --delete-after --timeout=10 --tries=1", "w")) == NULL)
{
perror("popen");
exit(1);
}
pclose(pipe_fp);
seconds1 = time (NULL);
vysledok = seconds1 - seconds0;
vysledokn = 1;
if(vysledok>9)
{
vysledokn = 0;
}
if(vysledokn==1)
{
seconds0 = time (NULL);
if (( pipe_fp = popen("wget http://www.aqua-fish.net/show.php?h=discusfish --delete-after --timeout=10 --tries=1", "w")) == NULL)
{
perror("popen");
exit(1);
}
pclose(pipe_fp);
seconds1 = time (NULL);
vysledok = seconds1 - seconds0;
if(vysledok>9)
{
if (( pipe_fp = popen("smplayer /home/janhvik/Desktop/temp/c/alarm.wav -close-at-end", "w")) == NULL)
{
perror("popen");
exit(2);
}
pclose(pipe_fp);
}
}
sleep(30);
}
return 0;
}
Compilation
Simply run
gcc c_source.c -o script.out
And then setup the first 2 scripts to be cron jobs. Let them run every minute. The third script should be run everytime you turn on your computer :) .
It worked on my Fedora Linux.
