Catégorie: "Développement"

Bug fixes admin & dev

November 2nd, 2005

Three small problems at work/personnal today.

  • I had to update the kernel of my boss's computer (running Ubuntu) in order to change an include.h into the GNU/Linux kernel (no more modification in the kernel). Then, I rebooted the computer but the data partition was not mounted. Getting stuff like :
    root@scully:/# mount /data/
    mount: /dev/hdb1 already mounted or /data busy
    Of course, hdb1 is not mounted and /data is not busy (fuser -v /data is your friend).

    After a few investigation, I found that evms is trying to access to the drive on boot and I guess it is not releasing the hard drive properly or something like that.
    Nov 02 17:07:28 scully _5_ Engine: is_volume_change_pending: Change pending: Volume /dev/evms/hdb1 needs to be activated.
    The dirty workaround is to launch evms AFTER the mount all options.
    mv /etc/rcS.d/S27evms /etc/rcS.d/S99evms

    Be carreful, this could cause side effects.

  • I had to debug an issue under the linux version of our softwares. Impossible to read big files (over 2 go).
    Then, I created a fake file of 3 go and made a small program to reproduce the issue.
    Here is the source :

    #include 
    
    void myRead(FILE * fichier){
    	/*lit le fichier caractere par caractere*/
    	char buf;
    	int ret=1;
    	
    	if (fichier!=NULL)
    		do
    			{        
    				ret=fread(&buf,sizeof(char),1,fichier);
    				printf("%c",buf);
    			}while(!feof(fichier));
    }
    
    int main () {
    	FILE *myFile = fopen( "bigfile","r" );
    	
    	if (myFile!=NULL) {
    		myRead(myFile);
    	}else{
    		printf("myFile not opened");
    	}
    
    	return 0;
    }
    

    Amazing, isn't it ?

    When I run this program (after tsize testsize.cpp), I only get a myFile not opened.
    Launching again this software with strace and I can see in the middle of the dump a :
    open("bigfile", O_RDONLY) = -1 EFBIG (File too large)

    After a few links, I finally found the solution :
    Add at the beginning of the source (before some includes) these three lines
    #define _FILE_OFFSET_BITS 64
    => defines which interface will be used by default
    #define _LARGEFILE64_SOURCE
    => permits the use of 64 bits functions
    #define _LARGEFILE_SOURCE
    => permits the use of fseeko() and ftello()
    Of course, it is possible to specify these define in the g++ command line like that : g++ -D_FILE_OFFSET_BITS=64 -o testsize testsize.cpp

    source

  • Sealers Cove - Wilson PromontoryLast but not least (I like this expression), an trick avoid stealer to make a direct link to one of your image on their website and wasting your bandwith. Personally, I don't care. I have plenty of bandwith and it represents a small part of the current traffic.
    However, I had to fix this problem for a website which offers legal mp3 & avi.
    The trick consists of using mod_rewrite. It checks the referent and if it is not from the official website and that it is trying to reach a file with a specific extension (mp3 and so on), we redirect the navigator to an other URL.

    Just put this few lines into your .htaccess and it should do it (if you have access to mod_rewrite for your website) :

    DirectoryIndex index.php
    RewriteEngine On
    
    # Rewrite Rules for files
    # if the referent is not empty
    RewriteCond %{HTTP_REFERER} !^$
    # if the domain is not our
    RewriteCond %{HTTP_REFERER} !^(.*)(domain.com|domain.com.au)(.*)$
    # if the extension if in the list 
    RewriteCond %{REQUEST_URI} \.(mp3|wmv|wma|zip|avi|mpg)$ [NC]
    # Redirect to an URL 
    RewriteRule ^(.*)$ http://sylvestre.ledru.info/ [L]
    

    Pretty simple isn't it ?

PS : why this image ? Well, this post is too technical... This picture has been taken last week end in Sealers Cove in Wilson 's Promontory in Victoria.

Edit : comments are closed. Thank you spammer.

L'importance de l'optimisation

Novembre 1st, 2005

La fréquentation... On l'espère sur chacun des sites que l'on lance. Une des contre partie est l'accroissement de ressources utilisées. J'avais pas réalisé comment un trafic très important peut impacter rapidement un serveur via un site mal optimisé.

Durant ces dernières semaines, j'en avais marre de voir le processeur de [i]mes[/i] serveurs de plus en plus utilisés par quelques sites. Prenant le kangourou par les oreilles, j'ai décidé de m'attaquer aux problèmes... Avec, en toute modestie, succès. Voila donc les deux cas réels que j'ai du traiter ces derniers temps :

* Le premier exemple est le passage à la dernière version (dawn - 0.9.1) de b2evolution.
Mon blog et le blog groupé (http://blog.jovialyteam.com) sont hébergés sur le même serveur. Ils se font spammer à une moyenne de 2/3 connexions HTTP à la seconde pour des fake referents vers des sites porno ou de médicaments de tout genre. Malgré les protections, les spammeurs trouvent toujours des contournements et leurs robots spammeurs se connectent toujours sur le site et entrainent le traitement PHP et SQL du site.
J'ai donc mis à jour b2evolution et l'impact sur les performances est phénoménal comme on peut le voir sur ce graphe :
Avant et après la maj de b2evolution
Avant et après la maj de b2evolution sur une semaine

(les piques sont normaux et causés par un autre programme).
On voit clairement l'impact... Impact qui se voit aussi sur la base de données en terme de requêtes SQL et donc en utilisation du serveur SQL.
Comme quoi, bien choisir son logiciel est important et malheureusement, il est très difficile d'évaluer ce critère dans le monde réel...

* Deuxième exemple. J'ai développé pour l'association australia-australie.com un système de carnet de voyage http://www.carnets.australia-australie.com/ sur l'Australie. A l'époque, je ne pensais pas que ça prendrait autant d'importance donc les questions de performance n'avaient pas été un point crutial dans le développement du site mais voila, c'est devenu un succès en terme d'utilisation et de fréquentation causant ainsi un ralentissement notable dans l'accès au site. J'ai donc regardé le code (que je ne touchais plus depuis quelques temps vu que je développe la nouvelle version ...) et je me suis rapidement aperçu que j'avais zappé de créer les index sur les clés secondaires (je sais, j'ai honte).
Par exemple, les commentaires sur les carnets fonctionnent en arbre et du à la version de MySQL à l'époque, je dois faire une requête par branche dans une fonction récursive. Autant dire quelque chose qui tire sur un carnet à forte fréquentation avec beaucoup de commentaires.
Je l'ai donc généré les index à tous les endroits nécessaires (enfin, tout ceux que j'ai vu) et la rapidité a été vraiment augmentée et l'utilisation processeur réduite par un facteur énorme... (J'ai l'impression de vendre une lessive en disant ça).
Evolution sur un mois avant et apres les index
Evolution sur un mois avant et apres les index

Moralité... utiliser les index de base de données...

Ceci dit, une chose que je déplore dans les applications web comme par exemple mediawiki, c'est la non ou pauvre utilisation des caches. Par cache, j'entend conserver une copie de la page web générée pour la reservir directement si le contenu n'a pas changé... Evitant ainsi tout le processus de génération classique (boucles, traitement, connexion sql...). Au contraire, ils refont tous le processus à chaque connexion sachant pertinemment que le ratio (nouvelle page devant être généré)/(page déjà généré) est toujours à considérer... L'utilisation d'un moteur de template comme smarty réglant ce genre de problème (j'avoue que c'est long, parfois complexe et prévu depuis le début ou dans une refonte mais on y gagne tellement ...). A la place, on préfère demander de nouveaux serveurs...

Le Spam tue !

Septembre 3rd, 2005

J'administre le serveur sur lequel tourne mon blog. Il héberge pas mal de sites. Aucun ne générant des trafics délirant mais des sites de trafic moyen.
En autre sur ce blog, c'est entre 400 et 1200 connexions par jour. Il y a aussi quelques autres blogs qui générent entre 200 et 500 connexions par jour. Bref, rien d'énorme. Ceci dit, dans ces chiffres se cachent les robots des Spammeurs qui viennent pourrir les commentaires, les référents et les trackballs. Les robots vont simuler les interventions humaines. C'est-à-dire qu'ils vont consulter les pages HTML et mettre le texte et valider les formulaires. Bien sur, pour chaque page générée pour un robot, le serveur doit parser et traiter les pages PHP, lancer les requêtes SQL, etc d'où une surcharge du serveur inutile.

Suite au commentaire de Ralphy, j'ai testé une fonction (BlockUntrustedVisitors() qui en plus a le bon gout de ne pas être limité à b2evolution) qui se rajoute dans le code de b2evolution. Celle-ci se charge de refuser l'accès au site dès la connexion (c'est-à-dire avant le gros du traitement PHP) les robots hébergés sur des IPs connues comme étant détournées (essentiellement des PC sous Windows bourrés de Spywares).

Bref, j'ai donc rajouté cette fonction et j'ai été très surpris de voir l'impact évident que ça a eu sur le serveur.
Ce graphe (généré par MRTG à partir d'un script qui utilise le programme sar fourni par sysstat) montre l'utilisation processeur avant l'ajout de la fonction et après (vers 7 heure du matin).


Utilisation CPU avant et après l'ajout de la fonction

On voit facilement une diminution de plus de moitié de l'utilisation processeur (25 % d'utilisation à 8/9 %, les piques étant le programme de génération des stats - donc rien à voir) alors que le traitement SQL n'est même pas réalisé sur ce serveur mais sur un autre en LAN.

Par là, je ne veux pas montrer que b2evolution est lent, ça n'est pas le point. C'est surtout pour montrer l'impact économique que le SPAM a actuellement sur Internet car pour être capable de gérer cet utilisation anormale, il faut mettre à jour les serveurs ou en rajouter ... (la modification du code n'étant pas toujours possible). J'en fait déjà fait la désagrable expérience avec les serveurs mail tous les jours depuis des années mais je n'avais pas réalisé qu'elle touchait tant les serveurs web ...

Mass DNS Test

July 3rd, 2005

Imagine that you are dirty with your DNS server. You make some modifications very often and you are not sure when your DNS server is up, RFC and running. Here is a little script which will automatically test some domains and send emails in case of error.

In order to test domains validity, I use DNSdoctor (http://www.dnsdoctor.org/), a fork from Zonecheck (http://www.afnic.fr/outils/zonecheck), a tool developed to perform verifications on the quality of the configuration (it is mandatory with a .fr to have the domain correctly configured). DNSdoctor exists with a few GUI :
- the web interface - http://demo.dnsdoctor.org/
- a classical application using GTK
- a command line application

Of course, I am using the last one to perform the automatic testing system.

As DNSdoctor has been made using Ruby, I made this script with this language (I don't want to have to install python for this script). It will call the DNSdoctor with the appropriate parameters. If an error is detected, it will send an email associated to the domain in the configuration.

If an error occurs, this kind of email will be sent :

ZONE  : ledru.info.
NS <= : akira.ecranbleu.org. [195.137.249.60]
NS    : radium.meaweb.com. [83.217.68.103]
NS    : trunks.ecranbleu.org. [195.137.249.61]

[> ICMP answer
w> Host doesn't reply to ICMP requests (firewall?)
=> radium.meaweb.com./83.217.68.103
=> akira.ecranbleu.org./195.137.249.60
=> trunks.ecranbleu.org./195.137.249.61

[> UDP connectivity
f> Server doesn't listen/answer on port 53 for UDP protocol
 | Ref: IETF RFC1035 (p.32 4.2. Transport)
 |   The DNS assumes that messages will be transmitted as datagrams or in
 | a byte stream carried by a virtual circuit. While virtual circuits can
 | be used for any DNS activity, datagrams are preferred for queries due
 | to their lower overhead and better performance.
 `----- -- -- - -  -
=> radium.meaweb.com./83.217.68.103

==> FAILURE (and 3 warning(s))
#!/usr/bin/ruby
require 'net/smtp'

###########" Parameters ###############
pathCommand="export LANG=en_EN; /usr/bin/dnsdoctor"
paramCommand="-q -vn,d,x,-c "
logFile="/tmp/massDNS.log"
subject="DNS error"
from="tech@linesurf.com"
testDNS= [
	{'domain'=>'ecranbleu.org',
	'email'=>'email@domain.com'},

	{'domain'=>'ledru.info',
	'email'=>'email@mondomaine.com'}
]

def sendmail(from,to,content)
	# --- Send using class methods
	msg = [ "Subject: Test\n", "\n", content ]
	Net::SMTP.start('localhost') do |server|
		server.sendmail( msg,  from , [ to ] )
	end
end

######### Don't edit under #############

command="#{pathCommand} #{paramCommand} "	
for domain in testDNS
	puts "Processing of #{domain['domain']}"
	commandLine=command + domain['domain']
	system(commandLine +'  > '+ logFile +' 2>&1')
	if ($? != 0) 
		content=""
		IO.foreach(logFile) { |line| content+=line }
		sendmail(from,domain['email'],content)
		puts "Erreur"
	end
	File.delete(logFile)	
end

Edit : comments are closed. Thank you spammer.

Argument list too long

Mai 3rd, 2005

I have to compile a big software for work. It is using the opencascade toolkit to develop and compile.
It compiles everything itself (nice but tricky).
However, I don't have too much control on the compilation directives and as it is automatic, it produces sometimes some huge command line to compile one lib (I have a gcc command line of 1300 lines ...). And the kernel refuses a command of that size with a nice :
/usr/bin/g++: Argument list too long. or /usr/bin/g++: Liste d'arguments trop longue. in French

As I don't want to hack Opencascade, the only "clean" solution I found is to recompile the kernel :

Edit the file /usr/src/linux/include/linux/binfmts.h
and change the 32 parameter to 64 to increase this limit. :

#define MAX_ARG_PAGES 32

And recompile the kernel ...

Here is the crappy trick !