Git pre-commit hook : Vérification de fichiers PHP et Shell avant de les commiter

Quand on utilise un gestionnaire de sources comme Git ou Subversion (si vous n’en utilisez pas pour vos développements, vous connaissez la priorité n°1 sur votre liste de tâches), il est très facile de faire en sorte que les fichiers que l’on cherche à commiter sur le serveur soient vérifiés avant d’être effectivement acceptés.
Cela permet d’éviter de propager du code incorrect, qui ne compile pas, avant même qu’il ne se retrouve sur le dépôt de sources (et donc chez les autres développeurs voire dans un processus d’intégration continue).

J’utilise Git avec un fournisseur de service SaaS (Github, mais j’ai aussi utilisé Bitbucket), et je suis donc obligé de mettre en place le script de pre-commit sur le poste de développement local. À la racine d’un repository Git, il y a un sous-répertoire “.git/hooks” qui sert à contenir les hooks, c’est-à-dire les programmes à exécuter en fonction de l’action effectuée. Par défaut, ce répertoire contient des exemples de scripts dont vous pouvez vous inspirer pour créer les vôtres (en shell).

Idéalement, il faudrait vérifier la syntaxe des fichiers quand on les ajoute avec “git add” ; malheureusement, il n’y a pas de hook sur cette étape. On est donc obligé d’attendre le moment où on tente de commiter les fichiers, mais cela implique qu’en cas d’erreur il faudra ajouter de nouveau la version corrigée du fichier, puis de retenter le commit.

Pour prendre la main juste avant que le commit ne soit effectué, il faut écrire un script nommé “pre-commit”, et le déposer dans le répertoire “.git/hooks” de votre repository. Ce script doit retourner une valeur égale à zéro si tout s’est bien passé, et une valeur supérieure à zéro si on a rencontré une erreur dans un fichier qui s’apprête à être commité.

Mon hook a pour but de vérifier que les fichiers PHP que je commite sont corrects du point de vue syntaxique (testé avec la commande “php -l ”), ainsi que les scripts shell (en utilisant l’outil shellcheck). Si des erreurs sont trouvées dans certains fichiers, elles sont affichées et le commit est interrompu.

Le hook est codé en PHP. Avant j’utilisais des scripts shell, mais je suis passé au PHP pour deux raisons : certains traitements sont plus simples en PHP qu’en shell (gestion des tableaux, manipulation de chaînes…) ; et j’ai ajouté la vérification de syntaxe pour des templates Smarty (le seul moyen de vérifier la syntaxe d’un template Smarty est d’interpréter le template, et ça ne peut être fait qu’avec du code PHP).

Version sans vérification Smarty

Pour commencer, je vais vous donner le code de mon script de pre-commit sans la vérification des fichiers Smarty (tout le monde n’en a pas besoin).

Vous pourrez remarquer que ce script utilise l’objet ANSI de ma bibliothèque FineBase, afin d’écrire dans la console en utilisant les directives ANSI (pour afficher des messages en gras, en couleur, etc.).
Vous pouvez aussi voir que ce script s’attend à ce que le programme shellcheck soit installé dans le répertoire /usr/bin (répertoire d’installation par défaut sur Ubuntu, mais aussi sur la plupart des distributions Linux).

#!/usr/bin/php
<?php

require_once('finebase/Ansi.php');

// repo root path
$rootPath = exec('git rev-parse --show-toplevel', $res, $ret);
if ($ret) {
        exit(0);
}
unset($res);

// get list of files
exec('git diff --cached --name-only --diff-filter=ACMR', $files);
if (!is_array($files)) {
        exit(0);
}
// array of errors
$errors = [
        'php' => [],
        'tpl' => [],
        'sh'  => [],
];
// process all files
$smarty = $compileDir = $cacheDir = null;
foreach ($files as $file) {
        if (substr($file, -4) == '.php') {
                // check PHP file syntax
                exec("git show :$file | php -l > /dev/null", $errors['php'], $ret);
        } else {
                // check inside the file
                $fp = fopen("$rootPath/$file", 'r');
                $shebang = trim(fgets($fp));
                fclose($fp);
                if ($shebang != '#!/bin/bash' && $shebang != '#!/bin/sh')
                        continue;
                // check shell file syntax
                if (!file_exists('/usr/bin/shellcheck')) {
                        print(Ansi::color('yellow', "⚠ Can't check shell script. You should install 'shellcheck'."));
                        continue;
                }
                exec("/usr/bin/shellcheck -s bash -f gcc $rootPath/$file", $checklines, $ret);
                if (!$ret)
                        continue;
                foreach ($checklines as $checkline) {
                        $check = explode(':', $checkline);
                        if (trim($check[4]) == 'error') {
                                $errors['sh'][] = $checkline;
                        }
                }
        }
}
// display errors
$return = 0;
if (!empty($errors['php'])) {
        print(Ansi::color('red', "⛔ ERRORS IN PHP FILE(S)\n"));
        foreach ($errors['php'] as $err) {
                print(" $err\n");
        }
        $return = 1;
}
if (!empty($errors['sh'])) {
        print(Ansi::color('red', "⛔ ERRORS IN SHELL FILE(S)\n"));
        foreach ($errors['sh'] as $err) {
                print(" $err\n");
        }
        $return = 2;
}
exit($return);

 

Version avec vérification Smarty

Cette version est juste un peu plus complète. Elle remonte toutes les erreurs de syntaxe que pourraient contenir les fichiers PHP, Shell et Smarty qu’on s’apprête à commiter.

#!/usr/bin/php
<?php

require_once('finebase/Ansi.php');
require_once('smarty3/Smarty.class.php');

// repo root path
$rootPath = exec('git rev-parse --show-toplevel', $res, $ret);
if ($ret) {
        exit(0);
}
unset($res);

// get list of files
exec('git diff --cached --name-only --diff-filter=ACMR', $files);
if (!is_array($files)) {
        exit(0);
}
// array of errors
$errors = [ 
        'php' => [], 
        'tpl' => [], 
        'sh'  => [], 
];
// process all files
$smarty = $compileDir = $cacheDir = null;
foreach ($files as $file) {
        if (substr($file, -4) == '.php') {
                // check PHP file syntax
                exec("git show :$file | php -l > /dev/null", $errors['php'], $ret);
        } else if (substr($file, -4) == '.tpl') {
                // check Smarty file syntax
                if (!$smarty) {
                        $compileDir = sys_get_temp_dir() . '/git_commit_smarty_compile';
                        $cacheDir = sys_get_temp_dir() . '/git_commit_smarty_cache';
                        if (!is_dir($compileDir)) {
                                mkdir($compileDir);
                        }
                        if (!is_dir($cacheDir)) {
                                mkdir($cacheDir);
                        }
                        $smarty = new \Smarty();
                        $smarty->compile_dir = $compileDir;
                        $smarty->cache_dir = $cacheDir;
                        $smarty->error_reporting = E_ALL & ~E_NOTICE;
                        // add here your list of Smarty plugin path
                        $pluginPathList = ['/path/to/lib/smarty'];
                        $pluginPathList = array_merge($smarty->getPluginsDir(), $pluginPathList);
                        $smarty->setPluginsDir($pluginPathList);
                }
                try {
                        // define the root dir of your templates, which should be a sub-directory of your git repository
                        $smarty->template_dir = "$rootPath/templates/";
                        $smarty->fetch("$rootPath/$file");
                } catch (\Exception $e) {
                        $errors['tpl'][] = ">> '$rootPath/$file' ($file)";
                        $errors['tpl'][] = $e->getMessage();
                }
        } else {
                // check inside the file
                $fp = fopen("$rootPath/$file", 'r');
                $shebang = trim(fgets($fp));
                fclose($fp);
                if ($shebang != '#!/bin/bash' && $shebang != '#!/bin/sh') {
                        continue;
                }
                // check shell file syntax
                if (!file_exists('/usr/bin/shellcheck')) {
                        print(Ansi::color('yellow', "⚠ Can't check shell script. You should install 'shellcheck'."));
                        continue;
                }
                exec("/usr/bin/shellcheck -s bash -f gcc $rootPath/$file", $checklines, $ret);
                if (!$ret) {
                        continue;
                }
                foreach ($checklines as $checkline) {
                        $check = explode(':', $checkline);
                        if (trim($check[4]) == 'error') {
                                $errors['sh'][] = $checkline;
                        }
                }
        }
}
// remove temporary files
if ($compileDir) {
        shell_exec("rm -rf $compileDir $cacheDir");
}
// display errors
$return = 0;
if (!empty($errors['php'])) {
        print(Ansi::color('red', "⛔ ERRORS IN PHP FILE(S)\n"));
        foreach ($errors['php'] as $err) {
                print(" $err\n");
        }
        $return = 1;
}
if (!empty($errors['sh'])) {
        print(Ansi::color('red', "⛔ ERRORS IN SHELL FILE(S)\n"));
        foreach ($errors['sh'] as $err) {
                print(" $err\n");
        }
        $return = 2;
}
if (!empty($errors['tpl'])) {
        print(Ansi::color('red', "⛔ ERRORS IN SMARTY FILE(S)\n"));
        foreach ($errors['tpl'] as $err) {
                print(" $err\n");
        }
        $return = 3;
}
exit($return);

 

Pensez à adapter la variable $pluginPathList en y mettant la liste des répertoires contenant vos plugins Smarty. Adaptez aussi $smarty->template_dir pour y indiquer le chemin vers le répertoire racine de vos templates Smarty (c’est utile lorsque vous faite des inclusions de fichiers en mettant des chemins relatifs à cette racine).

J’utilise ce hook depuis un certain temps maintenant. J’espère qu’il pourra aussi être utile à d’autres personnes.
En cherchant un peu sur le web, vous pourrez trouver plein de contributions du même type, qui pourront remplir vos besoins. Personnellement, je n’ai rien trouvé qui fasse les vérifications exactes dont j’avais besoin (PHP, Smarty et Shell). Donc voilà 😉

Dernière précision : Dans la mesure où ce script de pre-commit s’exécute en local sur le poste de développement, il est toujours possible de demander git à ne pas l’utiliser et donc forcer le commit des fichiers. Seuls des hook côté serveur peuvent éviter cela. Mais franchement, il n’y a strictement aucun intérêt à vouloir contourner ce type de sécurité.

Fonctionnement interne des langages de programmation

Juste pour le fun, voici quelques liens vers des sites qui détaillent le fonctionnement interne de plusieurs langages de programmation. C’est très intéressant à étudier.

Si vous connaissez d’autres sources d’information de ce type, n’hésitez pas à les ajouter dans les commentaires.

PHP
PHP Internals Book

Perl
Perl 5 Internals
Parrot

Lua
The Implementation of Lua 5.0 (PDF)
The Virtual Machine of Lua 5.0 (PDF)
A No-Frills Introduction to Lua 5.1 VM Instructions (PDF)

Java
The Structure of the Java Virtual Machine
JVM Internals blog

Python
Design of CPython’s Compiler
Python internals: Working with Python ASTs
Python’s Innards

Ruby
Ruby Under a Microscope
Ruby Internals (70 slides)

Dart
The Essence of Google Dart: Building Applications, Snapshots, Isolates

Javascript
The V8 JavaScript Engine
V8 Internals: Building a High Performance JavaScript Engine

.NET / CLR
Internals to .NET
Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects
.NET Type Internals – From a Microsoft CLR Perspective

Forth
A sometimes minimal FORTH compiler and tutorial for Linux (part 2)

Autres
The Potion Language

Edit : J’ai ajouté des liens Lua et Forth qui m’ont été transmis par @pchapuis. Encore merci !  🙂

Recrutement : Développeur PHP 5

Fine Media, l’entreprise que j’ai co-créé et dont je suis le directeur technique, est à la recherche d’un développeur web.

Présentation de l’entreprise

Nous sommes éditeurs de sites web. Notre activité principale porte sur les sites Ooreka, qui sont un ensemble de plus de 420 sites de niche, sur des sujets aussi variés que les fenêtres, la défiscalisation ou le home cinéma. C’est notre « encyclopédie de la vie pratique ».
Nous éditons aussi des sites communautaires, comme CommentFaitOn ou DcoPhoto.

Nous sommes localisés dans le 17è arrondissement de Paris (métro Villiers).

L’entreprise existe depuis 2007 et est une filiale du groupe Solocal (ex Groupe PagesJaunes) depuis 2011.
Nous sommes une vingtaine de personnes, et l’équipe technique comprend 9 personnes.

Environnement technique et méthodes de travail

  • Linux. On utilise de l’Ubuntu Server sur les serveurs, et de l’Ubuntu Workstation sur les postes de développement.
  • PHP 5. Tout est développé en PHP, en objet.
  • MySQL. On fait des requêtes assez compliquées. Il vaudrait mieux que vous sachiez la différence entre une sous-requête et une jointure.
  • Redis. Nous faisons de l’hybridation de bases, cela peut être l’occasion pour vous d’approcher le noSQL de près.
  • Temma. Nous utilisons notre propre framework MVC, qui est publié sous licence libre.

Nous travaillons suivant une méthode dérivée de SCRUM. Nous faisons des cycles itératifs d’une durée d’un mois (cf. l’article où j’en parlais).

Ce que vous aurez à faire

  • Améliorer notre framework MVC, ainsi que notre CMS. Ils sont petits et légers, des vrais jouets faciles à faire évoluer dans les directions qui nous intéressent.
  • Génie logiciel : modélisation des objets métier, évolution du modèle de base de données, développement orienté objet.
  • Gestion de projet : écriture des spécifications techniques, suivi du planning, supervision des tests.

Je cherche quelqu’un ayant déjà fait ses armes en développement Web, et qui aime ça. Un passionné avec des idées à faire valoir, ayant envie de les partager et de les appliquer. Une personne qui sache travailler en équipe, qui cherche à apprendre des choses nouvelles.

Alors si vous êtes ambitieux, si vous avez des idées techniques intéressantes, si vous aimez le Web et avez envie de bosser sur des trucs pointus et originaux, envoyez-moi votre CV à l’adresse amaury.bouchard@finemedia.fr.

Ajout : Suite à des questions, je préfère préciser que nous ne recherchons pas de prestataire, ni de développeur travaillant à distance. L’idée est d’embaucher quelqu’un qui fera partie intégrante de l’équipe − y compris dans sa localisation géographique.

Ils aiment le C et moi aussi

J’ai déjà écrit plusieurs articles sur les langages de programmation : ceux que je connais, le modèle objet, l’utilisation de TinyCC pour créer un interpréteur, quelques remarques sur les syntaxes, ainsi qu’un article dans lequel j’expliquais les forces du PHP (et qui a reçu des réponses qui me font toujours rire un an après).

J’ai déjà exprimé clairement que mes deux langages préférés sont le PHP et le C ; le premier pour sa souplesse, son adaptabilité et la rapidité avec laquelle on atteint son objectif ; le second pour sa simplicité, son efficacité et le fait qu’il donne un accès direct et transparent à la machine.

Et c’est justement du C dont je vais rapidement vous parler. On a souvent l’impression que c’est devenu avec le temps un langage complètement has-been, et que même ceux qui veulent faire du développement compilé nativement s’orientent tous vers le C++ ; et qu’à moins que vous ne fassiez du développement embarqué (style mbed ou Arduino), choisir le C est forcément un mauvais choix.

J’ai toujours été contre cette vision des choses, mais je me disais que je devais être un peu particulier dans mon genre.

Récemment, je suis tombé sur plusieurs articles sur le web, qui m’ont fait voir que je suis loin d’être le seul à penser que les qualités du C sont toujours intactes.

Popularité

L’index TIOBE est très connu ; il mesure la popularité des langages de programmation. Devinez quel est le langage le plus populaire actuellement ?

TIOBE juin 2013

 

Eh oui, il s’agit bien du C, qui se tire la bourre avec le Java depuis pas mal de temps. Comprenez bien qu’il s’agit d’un indice de popularité, pas d’un benchmark de performances ou une étude sur les qualités intrinsèques des langages ou sur les fonctionnalités qu’ils proposent.

Non, cela montre simplement que le C est toujours un langage très utilisé de par le monde.

Performances

C’est un peu une évidence, mais ça va toujours mieux avec des chiffres. Je connais deux sites qui proposent des benchmarks entre les langages de programmation, basés sur différents algorithmes (certains très théoriques, d’autres plus proches de l’usage réel) : The Computer Language Benchmarks Games et The Great Win32 Computer Language Shootout.

Je vous laisse regarder par vous-même, mais les différents compilateurs C se retrouvent régulièrement en tête − ou dans le peloton de tête − des résultats.

Les autres exemples

Pour tout vous avouer, l’idée d’écrire cet article a commencé à germer en lisant un post sur le blog de Damien Katz, le créateur de CouchDB et directeur technique de CouchBase. Ce post a pour titre The Unreasonable Effectiveness of C.
Dedans, il explique pourquoi il apprécie le C, et pourquoi de plus en plus de parties du CouchBase Server sont écrites en C (il est écrit en Erlang à la base). Son article est très clair, et le point de vue de quelqu’un avec autant d’expérience est forcément très intéressant. Je vous invite à le lire en entier.

Juste pour le plaisir, je vais vous traduire le premier paragraphe :

Pendant des années j’ai essayé de m’éloigner du C. Trop simple, trop de détails à gérer, trop vieux et plein de cochonneries, de trop bas niveau. J’ai eu des amours intenses et torrides avec Java, C++, et Erlang. J’ai construit des choses dont je suis fier avec chacun d’eux, et pourtant ils m’ont tous brisé le cœur. Ils ont fait des promesses qu’ils ne pouvaient pas tenir, créé des cultures qui mettent l’accent sur de mauvaises choses, et ont fait des compromis dévastateurs qui font souffrir douloureusement au final. Et je reviens à chaque fois au C.

Plus récemment, je suis tombé sur un article (en fait deux) écrit par Martin Sústrik, le co-créateur, architecte et principal développeur de ZeroMQ. Je vous ai déjà parlé de cette bibliothèque réseau (, et , ainsi que lors de conférences), c’est un incroyable morceau de logiciel.
Son article s’intitule Why should I have written ZeroMQ in C, not C++. Difficile de faire plus explicite. Là encore, je vous conseille de le lire en entier (ainsi que la seconde partie). C’est assez technique, il parle des exceptions et de la gestion mémoire, notamment. On peut ne pas être d’accord avec sa vision des listes intrusives, mais là encore son expertise rend son opinion intéressante.

Pour info, il a réimplémenté ZeroMQ en pur C. Le projet s’appelle nanomsg, j’ai commencé à l’utiliser, c’est une tuerie.

Et pour moi ?

J’ai commencé tout récemment à travailler sur un nouveau projet (pour occuper mon temps, comme s’il m’en restait de libre…). Si ce projet aboutit, il n’aura d’intérêt que par ses performances. Je me suis donc tourné vers le langage le plus rapide que je connaisse. Et comme à chaque fois que je refais un peu de C, c’est un grand plaisir.

Évidemment, il faut un peu plus de temps que si je codais les choses en PHP (ou un autre langage interprété), particulièrement quand on commence à vouloir manipuler des chaînes de caractères, des listes ou des tableaux associatifs. Et il faut courir après les bibliothèques nécessaires, là où les autres langages fournissent beaucoup de choses de base.
Mais l’impression de puissance est grisante. La mémoire est là, à portée de main, on en fait ce qu’on veut. On contrôle exactement les threads et les processus à notre guise. Pas d’overhead, pas de choses cachées, pas de “magie” qui fait le boulot à notre place. La maîtrise du code est totale, et en contrepartie il n’y a aucune aide derrière laquelle se réfugier.

Avantage secondaire, du code écrit en C compile partout et n’a pas d’autre dépendances que celles que vous avez choisies.

Bug des sessions PHP sous Debian/Ubuntu

Je suis tombé sur un truc un peu étrange récemment, sur mes serveurs de production.

Au moment de faire une mise en production, notre programme de déploiement a remonté une erreur inhabituelle. En regardant de plus près, je me suis rendu compte qu’il n’avait pas pu écrire sur le disque les fichiers correspondant aux nouvelles versions des projets. Pourtant, il restait encore énormément de place sur le disque dur (à peine 15% d’espace disque utilisé).
Le soucis venait du fait que tous les inodes du système de fichiers avaient été consommés. Wow, la vache. Avoir bouffé tous les inodes, alors que 85% d’espace disque est encore libre, ça voulait dire qu’un nombre incroyable de minuscules fichiers avait été créé.

Le premier réflexe est de se demander quel bout de code on a bien pu écrire, qui génère cette merde. Et pour analyser l’origine du problème, la première étape est déjà d’essayer de savoir dans quel répertoire ces fichiers ont été créés. Donc on a fait un script pour compter le nombre de fichiers dans chaque répertoire. La fête, quoi.

On a découvert qu’il y avait plus de 16 millions de fichiers dans le répertoire /var/lib/php5. Attendez… qu’est-ce qui peut bien avoir créé autant de fichiers dans ce répertoire ?
Pas besoin de chercher très longtemps pour s’apercevoir qu’il s’agit de l’endroit où PHP écrit les fichiers servant à stocker les sessions utilisateurs.

Mais normalement, les sessions sont effacées au bout d’un certain temps. Tout le monde sait ça. C’est d’autant plus étonnant que notre framework Temma utilise son propre système de sessions (stockées dans Memcache), et que donc nous ne devrions pas créer ces fichiers car les sessions PHP sont contournées.
J’ai commencé par essayer de comprendre pourquoi les fichiers de sessions n’ont pas été effacés après un certain délai. Ce comportement est géré dans le fichier de configuration de PHP, par les directives session.gc_maxlifetime, session.gc_probability et session.gc_divisor. Pour faire simple, une installation standard sous Ubuntu (et, semble-t-il, aussi sous Debian) prévoit que les sessions aient une durée de 24 minutes.

Par contre, il existe deux manières différentes de faire le ménage dans les sessions.
La première est de configurer PHP pour qu’à chaque requête entrante, il se donne une chance de faire le ménage parmi les sessions ouvertes. Cela est calculé avec les paramètres que j’ai cités juste avant. Par exemple, le ménage dans les sessions pourra être fait toutes les mille requêtes (ce qui veut dire qu’une requête sur mille sera ralentie par ce traitement supplémentaire).
La seconde manière est de faire tourner régulièrement un script, en le lançant par crontab, dont le rôle est de faire le ménage pour effacer les fichiers correspondant aux sessions qui sont arrivées à expiration.

Sur Ubuntu (et donc sûrement sur Debian aussi), c’est la seconde solution qui a été choisie. Mais le truc complètement incompréhensible, c’est que le script lancé par crontab est commenté !
Pour être exact, il s’agit du fichier /etc/cron.d/php5. Il ne contient qu’une seule ligne, dont la commande est censée s’exécuter toutes les demi-heures. Mais comme je le disais, cette ligne est commentée. Donc le ménage n’est jamais fait.

Dans notre cas, le truc particulièrement con, c’est que les sessions PHP n’auraient pas dû être utilisées. Comme je l’ai dit plus haut, notre framework possède son propre système de session. Le hic, c’est que lorsque j’ai ouvert ce framework sous licence libre, j’ai ajouté une petite évolution : C’est bien beau de gérer nos sessions dans Memcache, mais cette solution ne peut pas satisfaire tout le monde. Donc il possède un fallback qui l’amène à utiliser les sessions PHP si les sessions n’ont pas explicitement été configurées pour utiliser le cache.

Partant de là, le code qui s’occupe de nos médias (principalement l’affichage des images sur nos sites) a connu un petit bug de configuration, qui activait les sessions. Cela ne sert à rien, on est d’accord ; il n’y a pas besoin de session utilisateur pour servir une image.
Mais comme il n’était pas prévu que les sessions soient activées, elles n’étaient évidemment pas configurées pour être stockées en cache. Donc elles se sont retrouvées à passer par le mécanisme des sessions PHP.
C’est ainsi que nous nous sommes retrouvés à écrire des fichiers sur le disque dur pour chaque visiteur de passage sur nos sites…

Alors si jamais vous vous retrouvez à cours d’inode, commencez par regarder du côté des sessions, on ne sait jamais.

Retour sur l’Open World Forum / OSDC

Je l’avais annoncé il y a quelque temps, j’ai donné deux conférences à l’Open World Forum, le 12 octobre dernier.

Il n’y avait pas une foule énorme au track PHP, et donc ma présentation des démons en PHP s’est faite dans une ambiance plus cosy que lors du Forum PHP au mois de juin.

Malheureusement, cette conférence n’a pas été filmée. Tout ce que je peux faire, c’est de vous diriger vers ma page consacrée à ZeroMQ, sur laquelle vous pourrez trouver les slides de cette présentation.

Par contre, le « lightning talk » que j’ai donné au sujet de FineFS était filmé. Il s’agit d’une mini-conférence de 5 minutes chrono. Je trouve l’exercice toujours aussi plaisant.


[OSDC.fr 2012] Présentation de FineFS, un… par osdcfr

Pour terminer, si vous voulez vous marrer pendant 3 minutes 46, jetez un œil sur le lightning talk de Christian Aperghis-Tramoni. Une perle d’humour geek doublée d’un savoureux piège à trolls.

Conférence à l’Open World Forum, vendredi 12 octobre

Je donnerai une conférence à l’Open World Forum (en fait, à l’Open Source Developers Conference, qui se tient dans le cadre de l’Open World Forum) le vendredi 12 octobre 2012.

À 14h00, je présenterai la conférence “Démons en PHP, de inetd à ZeroMQ”, que j’avais déjà donné au Forum PHP en juin. Elle devrait durer 45 minutes + questions/réponses.

En fin de journée, je ferais une mini-conférence de 5 minutes, durant laquelle je présenterai le système de fichiers redondés FineFS.

Tout ça a lieu à l’Eurosites Georges V. Venez nombreux, ces conférences sont gratuites !

Edit : Pour le compte-rendu (avec une vidéo), c’est par ici.

PHP, le langage pour les geeks et les directeurs techniques

Ces derniers temps, on dirait qu’un nouveau sport international est apparu, dont la pratique consiste à dire pourquoi PHP est un mauvais langage (ici ou ) ou au contraire un bon langage de programmation (ici, ). J’avais décidé de ne pas participer à ce championnat, parce que c’est un peu stérile (et aussi parce que j’écris déjà suffisamment d’articles sur le PHP).

Mais finalement, j’ai changé d’idée. Non pas parce que j’ai soudainement envie de prendre la défense du PHP (tout le monde sait que c’est mon langage de prédilection), mais parce que je continue à m’intéresser aux différents langages de programmation ; et il me semble intéressant de partager avec vous quelques éléments qui ressortent de tout ça.

Le web d’abord

Ce n’est pas un scoop, PHP a été inventé pour créer des sites web. Ça fait très longtemps qu’on peut l’utiliser pour complètement autre chose (système de fichier redondé, interface graphique, …), comme n’importe quel langage de script. Mais c’est une réalité inscrite dans ses gènes.

Concrètement, cela se traduit par le fichier de configuration php.ini, qui offre − entre autres − la possibilité de définir la mémoire consommée lors de l’exécution d’une requête, ou la durée maximale d’un traitement. Ce genre de paramétrage est désormais possible avec Perl (grâce à mod_perl sous Apache), mais je n’ai pas trouvé d’équivalent exact avec Python ou Ruby (même en cherchant du côté de mod_python ou de FastCGI). Quoi qu’il en soit, cela explique pourquoi PHP a vite trouvé sa place dans les offres d’hébergement mutualisé.

Un langage qui évolue vite

De tous les principaux langages de programmation, je pense que PHP est celui qui évolue le plus vite. Si on regarde ce qu’il s’est passé ces 10 dernières années, il est indéniable que les concepteurs du langage ont fait un très gros effort d’amélioration et d’ajout de fonctionnalités.

En même temps, le code écrit il y a 10 ans a de grandes chances de fonctionner tel quel. Et l’ajout d’un modèle objet très complet, qui n’a plus à rougir d’aucun autre langage, n’empêche pas qu’il reste possible d’utiliser le PHP comme un simple langage de script procédural.

Les autres langages interprétés cherchent aussi à faire ce grand écart, mais j’ai l’impression que certains connaissent la double peine : ils n’évoluent pas très vite, et quand une version majeure est disponible, son taux d’adoption reste faible (Perl 6, Python 3).

Un langage qu’on connait déjà

Ce qui me semble être l’une des grandes forces du PHP, c’est qu’il emprunte la plupart de ses concepts à des langages très connus. Il suffit d’avoir des notions de C, C++, Java, Javascript, Perl ou Shell pour se sentir en territoire connu.

Le PHP n’est pas un langage académique ; il est rarement enseigné en écoles ou à l’université, au contraire de la plupart des langages sus-cités. Pouvoir passer de l’un à l’autre facilement a forcément contribué à augmenter le nombre de personnes qui développent en PHP. Même si le Python, le Ruby et le Lua font appels à des concepts très intéressants, ces mêmes concepts nécessitent parfois un reset mental qui peut faire un peu peur.

Un langage simple et souple

Les langages de script modernes partagent souvent la caractéristique d’avoir un typage dynamique, voire faible. Cela permet de développer plus rapidement qu’avec des langages à typage statique (souvent associé à un typage fort). Les détracteurs objectent que ça favorise l’écriture non-réfléchie de code, qui devient vite un plat de spaghetti, mais c’est très apprécié dans le cadre de développements incrémentaux.

Continuer la lecture de « PHP, le langage pour les geeks et les directeurs techniques »

Normes PHP : PSR-2… aïe, raté

Si vous êtes versés dans le monde PHP, il y a quelques chances que vous ayez entendu parler de la norme PSR-0. Par contre, les normes PSR-1 et PSR-2 sont plus récentes, et de fait moins connues.

Ces normes sont définies par le « PHP Framework Interoperability Group » (FIG en abrégé), un groupe d’acteurs connus du monde PHP, contributeurs de frameworks, ORM et bibliothèques parmi les plus connus. Tout ce petit monde s’est réuni pour tenter de définir un ensemble de règles communes, afin de faciliter l’utilisation de différentes briques logicielles écrites en PHP.

L’effort est louable. La norme PSR-0 était absolument nécessaire, mais correspondait plutôt à la normalisation d’une bonne pratique répandue. La norme PSR-1 me semble personnellement pleine de bon sens.

Par contre, quand j’ai lu le contenu de la norme PSR-2, je me suis dit qu’ils avaient fait fausse route. Je sais bien qu’il faut parfois faire certains choix. Mais après avoir exposé les choses à mes développeurs, je me suis décidé à écrire un article sur le sujet.

PSR-0

La norme PSR-0 a pour but de faciliter le chargement automatique d’objets (aussi connu sous le nom d’autoload), par la mise en place d’espaces de nommage correspondant aux arborescences de fichiers sur disque. Le tout est très cohérent et très utile.

Comme je le disais plus haut, PSR-0 formalise une bonne pratique qui était déjà assez répandue.

PSR-1

La norme PSR-1 se repose sur PSR-0, et y ajoute quelques détails qui ont leur importance :

  • Seuls les tags PHP <?php et <?= sont acceptés.
  • Le code PHP doit être encodé en UTF-8.
  • Les fichiers PHP peuvent contenir de la déclaration de symboles ou produire des écritures, mais pas les deux à la fois.
  • Les noms de classes doivent être écrits en StudlyCaps.
  • Les constantes s’écrivent en majuscule.
  • Les méthodes s’écrivent en camelCase.

Encore une fois, tout cela n’est que du bon sens, et était déjà largement utilisé.

La seule chose qui manque, à mon avis, concerne les attributs de classe : leur écriture est volontairement laissée à l’appréciation de chacun. J’aurais personnellement préféré les normaliser en camelCase.

PSR-2

PSR-2 est une norme qui concerne le style d’écriture du code. Je vous laisse lire son contenu, mais moi ça m’a fait le même effet qu’à Brian Moon, qui a écrit un très bon article sur le sujet. Je vous invite aussi à lire son article, mais tout se résume avec une image :

http://xkcd.com/927/

Je trouve cette image savoureuse. C’est tellement vrai, non ?  🙂

Continuer la lecture de « Normes PHP : PSR-2… aïe, raté »

Recrutement : Administrateur système

Le poste d’administrateur système n’est plus à pourvoir. Merci à tous ceux qui m’ont envoyé un CV.

Fine Media, l’entreprise que j’ai co-créé et dont je suis le directeur technique, est à la recherche d’un administrateur système / responsable d’exploitation.

Présentation de l’entreprise

Nous éditons des sites web communautaires, comme CommentFaitOn ou DcoPhoto, et des sites « de niche » comme Le guide de la cuisine, ou les sites ComprendreChoisir (sur la fenêtre, la défiscalisation, le home cinema, les standards téléphoniques, …).

L’entreprise est bientôt âgée de 5 ans, comprend environ 25 personnes et est devenue une filiale du groupe PagesJaunes depuis l’été dernier. Le cadre et les projets sont dynamiques et motivants, l’équipe est jeune et très motivée.
Nous sommes localisés dans le 17è arrondissement de Paris (métro Villiers).

Définition du poste

Le poste d’administrateur couvre un champ d’action assez large.

Au quotidien, cela implique :

  • Maintenance du réseau interne de l’entreprise, qui comprend près de 30 postes de travail, 4 serveurs et un NAS. Nous avons un second réseau dédié à la téléphonie (voix sur IP).
  • Administration des serveurs de production, soit 8 machines hébergées en datacenter.
  • Exploitation : Mise en pré-production et en production de nos projets, déroulement des cahiers de tests. Amélioration de nos procédures de suivi et de documentation.
  • Monitoring de nos serveurs et applications.
  • Sauvegarde et archivage des données de production et du réseau interne.

Je cherche quelqu’un qui puisse aussi participer aux évolutions que nous avons commencé à mettre en place sur notre architecture :

  • Expertise en base de données (configuration MySQL, optimisation de requêtes, réplication de bases).
  • Amélioration de la montée en charge de nos serveurs Web.
  • Étude de solutions de virtualisation (KVM) et noSQL (Redis).

Environnement technique

  • Linux : Tous nos serveurs tournent sous Ubuntu, ainsi que la plupart de nos postes de travail.
  • Web : Nos applications sont écrites en PHP, exécutées par Apache, et utilisent des bases de données MySQL.
  • Serveurs : Nos serveurs de productions sont majoritairement des bi-Xeon QuadCore/16 GO, avec des disques allant de 300 GO à 750 GO en RAID. Les serveurs internes tournent sur du matériel classique, certains sont virtualisés.
  • Scripting : Quelques scripts d’administration sont écrits en shell, mais la plupart de nos outils sont écrits en PHP.

Une migration de plate-forme de production est prévue à court terme, j’aimerais que le nouvel administrateur participe pleinement à son design et à sa mise en place.

Détails

Le poste est à pourvoir dès que possible.
C’est un CDI à temps complet.
Le salaire est en fonction de l’expérience et des compétences.

Si vous êtes intéressés, envoyez-moi votre CV à l’adresse amaury.bouchard@finemedia.fr.