Played with DTrace

Today, I installed NexentaOS on a Grid5000 cluster node. NexentaOS is basically Debian GNU/kOpenSolaris (Debian userland, with an OpenSolaris kernel. APT repository here). It works very well (good hardware support & detection, nice GNOME desktop). And I got the chance to play with DTrace.

Before writing this blog entry, I was considering writing a LinuxFR article about DTrace, when I came across this LinuxFR “journal” about Solaris 10, which gave me a good laugh. The best part is :

– DTrace : Sorte de surcouche de strace/ltrace. C’est peu intéressant. En démonstration, un type utilise DTrace pour “découvrir” que lancer une xterm écrit dans ~/.bash_history. C’est presque comique. (In approximate english: DTrace : a sort of layer above ltrace/strace. Not really interesting. In the demo, the developer used DTrace to “discover” that running xterm writes in ~/.bash_history. It’s nearly funny.)

It’s funny how people continue to compare DTrace to strace. It’s like comparing the GNOME project with fvwm. Yeah, both of them can display windows, and there are still people thinking that fvwm is enough for everybody.

OK, back to DTrace. DTrace is a tracing framework, which allows a consumer application (generally a D script) to register with some DTrace providers (probes) and get some data. This nice graph from the DTrace howto explains it much better than I do :

Most system monitoring tools on Linux use polling : they retrieve some data from the system at regular intervals (think of top, “vmstat 1”, …). DTrace changes this and uses push instead, which allows to monitor events that you wouldn’t notice on Linux. It also allows to monitor much more stuff than current Linux tools, in a very easy and clean way.

With DTrace, you can monitor a lot of stuff and find the answer to a lot of questions, like :

  • Monitor process creation, even the short ones. The execsnoop script (which would be a one-liner if you remove the output formatting, and is available in the DTrace Toolkit) shows that logging in by ssh and running for i in $(seq 1 3); do /bin/echo $i; done runs the following processes :
         0   1172   1171 sh -c /usr/bin/locale -a     0   1172   1171 /usr/bin/locale -a     0   1175   1173 -bash     0   1177   1176 id -u     0   1179   1178 dircolors -b     0   1174   1173 pt_chmod 9     0   1180   1175 mesg n     0   1181   1175 seq 1 3     0   1182   1175 /bin/echo 1     0   1183   1175 /bin/echo 2     0   1184   1175 /bin/echo 3 
  • Monitor user and library function calls, and profile them like gprof (yeah, DTrace can replace gprof)
  • Monitor system calls for the whole system or a specific app (yeah, DTrace can replace strace, but you already knew that ;). And you don’t need to restart the app before monitoring it.
  • Replace vmstat. Of course, you can also get the usual vmstat results, but only for events caused by a specific process.
  • Mesure the average latency between GET requests and their result when you browse the web using mozilla. DTrace does this by monitor write syscalls issued by your browser containing a GET and mesuring the delay before the subsequent read returns.
  • Monitor all open syscalls issued on the whole system
  • Monitor all TCP connections received by the system
  • Analyze disk I/O : how much data was written/read to/from the disk, by which process. Nice way to understand buffering and I/O scheduling.

Another example combining rwsnoop and iosnoop :

  1. I start rwsnoop -n bash (read/write monitor, only on processes named bash) and iosnoop -m / (I/O monitor, only on the root partition)
  2. I run : echo blop > t
  3. rwsnoop shows all the read/write calls issued to write to my pseudo-terminal, and the write call to /root/t :
       UID    PID CMD          D   BYTES FILE [...]     0   1175 bash         R       1 /devices/pseudo/pts@0:1     0   1175 bash         W       1 /devices/pseudo/pts@0:1     0   1175 bash         W       5 /root/t     0   1175 bash         W      32 /devices/pseudo/pts@0:1     0   1175 bash         W      17 /devices/pseudo/pts@0:1 
  4. iosnoop doesn’t display anything. But when I run sync :
       UID   PID D    BLOCK   SIZE       COMM PATHNAME     0  1264 W    96640   1024       sync /root/t 
  5. We can see that the write is buffered in the kernel. And that I the 5 chars to my file were transformed in 1024 bytes written to the disk. (Question for the reader: why 5 ? Yeah, it’s easy)

Short conclusion: DTrace looks fantastic. As a toy, it allows to demonstrate/understand the inner workings of Solaris. As a tool, it can probably provide A LOT of useful info, especially since writing DTrace providers seems quite easy (Ruby provider, PHP provider.

Second short conclusion for those who really haven’t understand anything (some LinuxFR readers ;-) : as you can see, when you run echo blop > t, “blop” is actually written to disk in /root/t. Fabulous, isn’t it ?

Ouverture de Planet JabberFR

Gr�ce au travail de Talou, JabberFR.org propose maintenant Planet.JabberFR.org, un agr�gateur des blogs francophones parlant de Jabber. N’h�sitez pas � contacter Talou si vous avez une cat�gorie “Jabber” sur votre blog ! (voir aussi le thread sur le forum de JabberFR.org � propos de �a).

Je profite de ce billet pour placer un lien vers un article co-�crit avec Nyco sur LinuxFR.org : Jabber explose.

Jabber for the masses

Big news in France : the radio Skyrock released SkyMessenger (nicknamed SM), a Jabber-based instant messaging service. Some facts :

  • Skyrock is famous in France for Skyblog, its very successful blog service, with more than 3.4 millions active blogs. If only a few Skyblog users start using SkyMessenger, it still means a lot of new Jabber users.
  • The service seems to be pure-Jabber. Not a modified, incompatible version as in Livecom. People managed to connect using Gajim.
  • The client is heavily based on Gajim and released under the GPL.
  • The service is only a Beta for now, with a limited number of downloads.
  • The address used by the server is skymess.com. Only port 5222 is open, with SASL enabled.
  • It seems that the business plan is to provide information through the IM service, about updated skyblogs for examples.
  • Server-to-server (s2s) communications are currently disabled. Some well-informed geeks seem to think that they plan to open it. It is confirmed by the add contact dialog, with proposes to add contact of type icq, msn, wanadoo, etc …

Jabber clients and OS usage stats

I used XMPP4R to do some stats about Jabber clients usage on the Apinc Jabber server, which hosts im.apinc.org, jabber.fr, and many more using virtual hosting.

The stats were done by sending jabber:iq:version requests to online users, and 651 replies were received. It was done at 6:30 PM, french local time. Here are the results :

Systems :

  • GNU/Linux : 34% (226)
  • Windows: 34% (223)
  • MacOS : 23% (150)
  • Others (AmigaOS, FreeBSD, NetBSD, OpenBSD, SunOS) : 1% (7)
  • Unknown (Gaim doesn’t always report the sytem) : 6% (45)

Clients :

  • Psi : 28% (186)
  • gaim : 25% (166)
  • iChatAgent : 18% (121)
  • Kopete : 7% (46)
  • libgaim : 3% (23)
  • Gajim : 3% (23)
  • Pandion : 2% (18)
  • Trillian : 2% (16)
  • Miranda : 1% (13)
  • neos : 1% (10)
  • Exodus : 1% (8)
  • BitlBee : 0% (6)
  • Tkabber : 0% (4)
  • Imendio Gossip : 0% (3)
  • JAJC : 0% (2)
  • webjabber.net : 0% (2)
  • Gabber : 0% (1)
  • Jabberwocky : 0% (1)
  • Mafia : 0% (1)
  • JETI : 0% (1)

The results might be biased by the facts that :

The script to do the mass-jabber:iq:version sending is available in the XMPP4R SVN repository (data/doc/xmpp4r/examples/advanced/versionpoll.rb). The ruby script to analyze results can be sent on demand. So please run the scripts on your servers :-)

"Faux" espaces avec Ubuntu

Depuis que j’utilise Ubuntu, j’ai un problème assez embêtant. De temps en temps, je tape un espace, et ça fait des choses comme ça :

***lucas@blop:~$ ls | grep a bash:  grep: command not found

Plutôt étrange, non ? Après des mois où j’ai simplement accepté ce petit désagrément, j’ai pris le taureau par les cornes et j’ai essayé de comprendre.

Le caractère qui s’affiche n’est pas un espace (code ascii 0x20) mais un espace insécable (code ascii 0xc2a0). Oui, mais pourquoi s’affiche-t-il sous Ubuntu, et pas sous Debian, par exemple ? En fait, le clavier “français” par défaut sous Ubuntu est fr-latin9, alors que sous Debian, on utilise généralement fr. Et si on regarde /etc/X11/xkb/symbols/fr, on comprend vite le problème : fr-latin9 complète fr en rajoutant plein de caractères accessibles via la touche ALTGR. Par exemple, Ë s’obtient avec ALTGR + Maj + d. Le comportement de la barre d’espace change également, avec l’envoi d’un Nobreakspace lorsqu’on fait ALTGR + espace.

En tapant “ls | grep a” je relâche parfois ALTGR après avoir appuyé sur espace, d’où l’apparition de ce caractère.

Solutions : il y en a plusieurs.

  • Utiliser fr à la place de fr-latin9 en supprimant Option “XkbVariant” “latin9” dans /etc/X11/xorg.conf (ne pas oublier de redémarrer X ensuite, évidememment).
  • Utiliser xmodmap pour modifier le comportement de la barre d’espace avec la commande xmodmap -e “keycode 65 = space space space NoSymbol space” ou simplement xmodmap -e “keycode 65 = space”. Pour que le changement soit durable, on peut ajouter keycode 65 = space à son fichier .xmodmap.
  • Apprendre à taper : oui, mais c’est dur, car on ne voit pas la différence entre un espace insécable et un espace. Certains éditeurs permettent d’utiliser des mappings pour remplacer certains caractères. Dans vim, par exemple, on peut utiliser imap <espace insécable ici> X. Ainsi, les espaces insécables sont remplacés par des “X”, et plus facilement détectés.

La liste des combinaisons de touches disponibles est visible dans le fichier /etc/X11/xkb/symbols/fr. Je la recopie ici :

//  ____                                     _________ _____________ _______ // | S A| S = Shift,  A = AltGr + Shift     | Imprime | Arrêt défil | Pause | // | s a| s = normal, a = AltGr             |  Exec   |             | Halte | //  ¯¯¯¯                                     ¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯ //  ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ _______ // | ½ "| 1 ·| 2 É| 3 ,| 4 '| 5 "| 6 || 7 È| 8 ¯| 9 Ç| 0 À| ° ÿ| + °| | | a â| z å| e ¤| r ç| t þ| y ý| u û| i î| o ô| p ¶| ^ ~| £ ê|   | W  | X  | C  | V  | B  | N  | ?  | .  | /  | §  |     ^     | // | |   | 

Comment se faire haïr de son hébergeur en quelques minutes

Disclaimer : toute ressemblance avec le code d’un site existant permettant d’échanger des maisons est totalement fortuite.

Il est très facile d’abuser de MySQL pour le transformer en une arme de destruction massive pour les performances de votre hébergeur. Il y a deux manières très simples d’y arriver :

  • Transférer le plus souvent possible d’énormes quantités de données du serveur SQL au serveur web. Bien sûr, votre script n’a pas besoin de toutes ces données, mais utiliser un SELECT restreint au lieu d’un SELECT *, ou pire, utiliser LIMIT, c’est tellement compliqué … alors que c’est si simple à faire en PHP. Par exemple, dans de vieilles versions de SPIP, la fonction chargée de nettoyer le cache (stocké dans MySQL) transférait l’ensemble du cache avant de décider si chaque entrée devait être conservée ou non. (C’est corrigé depuis février 2005 d’après le CVS de SPIP)
  • Une autre manière plus pernicieuse est de générer dynamiquement des requêtes SQL sans se poser la question des cas extrèmes de requêtes générées. Prenons un petit exemple.

Créons une petite table :

CREATE TABLE `torture` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT , `value` INT, PRIMARY KEY ( `id` ) ) TYPE = MYISAM ;

À l’aide d’un petit script PHP, remplissons là avec 10000 valeurs, ce qui n’est pas si énorme que ça.

for ($i = 0; $i  

Maintenant, la partie intéressante : générons dynamiquement une requête.

 $sql = "SELECT id FROM torture WHERE TRUE"; for ($i = 0; $i  ".rand(0, 10000); }

Vous l'aurez compris, pour n = 10, ça donne qqchose comme SELECT id FROM torture WHERE TRUE AND value <> 14647 AND value <> 9936 AND value <> 10106 AND value <> 8136 AND value <> 5952 AND value <> 6908 AND value <> 14290 AND value <> 15359 AND value <> 2179 AND value <> 8005.

En se débrouillant pour passer le paramètre n à la page, on peut facilement tester pour différentes valeurs de n. J'ai testé sur le nouveau serveur MySQL d'Apinc, peu chargé et très performant. Si avec n = 10, la requête ne met que 0.03s à s'exécuter, elle met 2.8s avec n = 1000, et 22s (aye) avec n = 5000. Avec n = 10000, on atteint 38s.

Histoire d'être complet, on peut préciser qu'ajouter un index sur la colonne value ne change rien : on n'évite pas l'évaluation pour chaque ligne de la table. Par contre, en exprimant la même requête sous la forme SELECT id FROM torture WHERE value NOT IN(2791, 962, 49, 5845, 4425, 4129, 9905, 6468, 9681, 5776), on la transforme en une requête s'exécutant immédiatement (0.05s avec n = 10000)

Conclusions :

  • IN et NOT IN, c'est bien(tm).
  • Les requêtes générées dynamiquement sans connaitre leurs tailles, c'est mal(tm).

Le format RST : reStructuredText

Le format RST (reStructuredText) est un format ouvert WYSIWYG très simple et très pratique, avec un rapport signal/bruit proche de l’optimal. Son cas d’utilisation typique est l’écriture de petits documents (TODO lists, résumés, courts articles, etc…). Il permet d’écrire des documents naturellement, avec simple éditeur de texte. Mais prenons plutôt un petit exemple :

 ================= Titre du document ================= Titre de section ================ Titre de sous-section --------------------- Titre de sous-sous-section ~~~~~~~~~~~~~~~~~~~~~~~~~~ ceci est un paragraphe ceci est un paragraphe ceci est un paragraphe ceci est un paragraphe ceci est un paragraphe ceci est un paragraphe ceci est un paragraphe ceci est un paragraphe ceci est un paragraphe ceci est un paragraphe ceci est un paragraphe. - Une liste - 2eme item   * imbrication de listes   * imbrication de listes, 2eme item - 3e item 1) liste ordonnée 2) suite de la liste ordonnée --------- Il y avait une ligne de séparation avant ce paragraphe. Une autre section ================= Les liens comme http://www.perdu.com sont transformés dans la version HTML. On peut aussi faire des liens avec des titres comme `ce lien <http://www.perdu.com>` 

Et on peut exporter vers de l’HTML (XHTML 1.0 Transitional, en fait), du LaTeX (pour faire du PostScript ou du PDF) ou du XML (idéal si vous maitrisez XSLT). Le convertisseur vers l’HTML est suffisamment rapide pour l’exécuter depuis un fichier PHP : ca vous fait un moyen de lire facilement votre TODO list à distance.

Pour installer rst2html, rst2latex et rst2xml sous Debian, c’est le paquet python-docutils (RST étant utilisé pour écrire de la doc Python).

Si vous voulez en savoir plus :

Faire le ménage sur son Ubuntu

Si vous utilisez Ubuntu depuis les temps héroïques où Ubuntu s’appellait encore no-name-yet, ou si vous passez votre temps à essayer tous les paquets disponibles, votre système a probablement besoin d’un peu de nettoyage.

D’abord, il y a les paquets que vous avez installé il y a longtemps, et qui ne sont plus dans Ubuntu. Hé oui, ça arrive. Et vous ne voulez pas garder ces paquets installés, car plus dans Ubuntu = plus de mises à jour de sécurité ! Pour les trouver, rien de mieux à ma connaissance qu’un sudo apt-show-versions |grep -v uptodate, qui liste tous les paquets pas à jour.

Une autre plaie : tous ces programmes que vous avez installé une fois pour les essayer, mais que vous n’utilisez plus depuis longtemps. Pour commencer, un deborphan vous listera les bibliothèques sur lesquelles aucun autre paquet Debian ne dépend. Celles là, il y a de fortes chances pour que vous puissiez les supprimer les yeux fermés.

Mais deborphan ne traite que les bibliothèques (ou alors, avec l’option -a, mais c’est pas évident à utiliser). Heureusement, il y a debfoster. debfoster vous demande si vous souhaitez conserver les programmes, mais d’une manière intelligente. Ainsi, par exemple, il commencera par vous demander si vous voulez garder ubuntu-desktop. Et ne vous demandera plus rien sur les paquets sur lesquels gnome dépend si vous répondez oui. Vous pouvez aussi purger un paquet : supprimer ce paquet, ainsi que tous les paquets cachés derrière et qui ne sont pas nécessaires à une autre feuille du graphe de dépendances. debfoster stocke ses informations dans un fichier, /var/lib/debfoster/keepers, qu’il suffit de supprimer pour faire oublier à debfoster tous les réponses qu’on lui a donné lors de lancements précédents.

Désolé, je n’ai pas de recettes miracles pour ranger son $HOME, par contre.

Mettez de la couleur dans votre terminal

Quand on débugge, parfois, on préfère utiliser des printf un peu partout que des vrais outils comme gdb. Simplement parce que parfois, gdb est inutile, ou insuffisant. Mais, à force de mettre des traces partout, la sortie devient vite illisible. Une solution pour éviter ça est d’utiliser de la couleur.[0]

Pour ça, on peut utiliser les caractères d’échappement d’xterm, c’est très facile et ça marche à peu près partout (en tout cas, là où c’est utile). Voici un petit exemple qui compile :

#include <stdio.h> int main() {    int i;    for (i = 30; i <= 37; i++)       printf("\e[%dmforeground %d\n", i, i);    printf("\e[m"); /* Raz */    for (i = 40; i <= 47; i++)       printf("\e[%dmbackground %d\n", i, i);    printf("\e[1;4;34;41mTexte bleu sur fond rouge en gras souligné\n");    printf("\e[0;39;49m\n"); /* Raz */    return 0; } 

Pour avoir la liste complète, c’est sur cette page. Attention, ça se lit comme une grammaire, c’est pas forcément évident au début.

[0] Il y a des gens qui, pour débugger, utilisent le son. C’est assez pratique pour repérer des patrons dans le comportement des programmes, l’oreille est très douée pour ça. Désolé, je ne trouve plus la référence… Si qqun connait…

Update : sur le meme sujet, un article de Linux Journal.