Mettre à jour ses sites Worpdress en quelques minutes, en ligne de commande

L’utilitaire wp-cli.phar est le « drush » de Drupal : il permet de lancer tout un tas de commandes Wordress habituellement faites via l’interface Web, en ligne de commande.
C’est plus rapide et scriptable !

Personnellement, j’utilise un utilisateur Linux différent pour chacun de mes sites.
Afin de simplifier la chose, j’ai choisi une installation globale de wp. J’en dispose ainsi pour tous mes sites.
Il faut donc configurer sudo pour donner les permissions à chacun de ces utilisateurs d’exécuter WP :

  1. Installer wp en suivant la doc d’install, tout simplement. Vous devez ensuite avoir votre script dans /usr/local/bin/wp.
  2. La partie un peu pénible peut être de configurer SUDO, car c’est un peu capricieux parfois…
  3. N’oubliez pas de donner les droits d’exécution à votre script wp pour les utilisateurs qui vont l’utiliser (ou à « others », chmod  755 /usr/local/bin/wp)

Ajouter les lignes suivantes dans votre configuration SUDO, en adaptant selon vos besoins (users, etc.)

User_Alias      GROUP_WP = web_AAA, web_BBB, web_CCC

Cmnd_Alias      CMD_WP = /usr/local/bin/wp

# le groupe des users WP a le droit aux commandes CMD_WP
GROUP_WP       ALL = NOPASSWD: CMD_WP

Ca vous permet ensuite de lancer la commande « wp » comme suit, sachant que je respecte une norme commune pour tous mes sites : chaque DOCUMENT_ROOT est contenu dans le sous-répertoire « www » du HOMEDIR.

sudo -u web_AAA -i -- wp core update --path=/home/web_AAA/www

 

Vous pouvez pousser le bouchon en vous créant un bash pratique, afin de mettre à jour tous vos WordPress en masse :

#!/bin/bash
# WordPress users (name of their home directory)
users=('web_AAA' 'web_BBB' 'web_CCC')

for user in "${users[@]}"
do
  echo "Upgrading $user wordpress and its plugins"
  sudo -u $user -i -- wp core update --path=/home/$user/www
  sudo -u $user -i -- wp plugin update --all --path=/home/$user/www
  sudo -u $user -i -- wp theme update --all --path=/home/$user/www
done

Et voilà ! Enjoy 😀

Sauvegarder les configs de son serveur Linux

Comment stocker vos fichiers de configurations Linux sur un dépôt GIT ?

ATTENTION, c’est une approche simpliste : l’inconvénient majeur de cette technique est de ne pas pouvoir conserver les permissions de chaque fichier/répertoire. GIT n’est pas non plus une solution de backup hein (http://serverfault.com/questions/341199/git-as-a-backup-tool) … il y a bien des outils qui tentent de le faire, je ne les ai pas testé, l’idée est de rester simple.

Au départ, l’idée était de faire un repo GIT, mais donc le worktree serait « / ».
Le souci de cette technique est que le « git status » a tendance à planter, probablement en raison du trop grand nb de fichiers/répertoires que ça représente, voire parce qu’il y rencontre d’autres repos GIT qui le perturbent, etc.

Technique retenue :
Un bête script SH pour copier nos fichiers dans le dépôt GIT.

  1. Créer vous un compte sur https://bitbucket.org, celui-ci permettant de créer des « repositories » privés, gratuitement, contrairement à Github, qui nécessite un abonnement pour avoir des « repos » privés.
  2. Côté serveur, créer un projet GIT qui stockera votre repository GIT ainsi que d’autres fichiers si besoin, mais la plupart de vos fichiers seront en dehors de ce répertoire.
    cd /root && mkdir configs
    cd configs
    git init
    git remote add origin git@bitbucket.org:##username##/##repository-name##.git
  3. Ajouter votre script de sauvegarde backup.sh
    BACKUP_DIR=/root/config/backup
    
    # Votre liste de fichiers/répertoires à sauvegarder
    files=('/etc/automysqlbackup' '/etc/rkhunter.conf' '/etc/ntp.conf' '/etc/fail2ban' '/etc/apache2' '/etc/nginx' '/etc/network/interfaces' '/etc/proftpd' '/etc/mysql' '/etc/resolv.conf' '/home/droits.sh
    ' '/root/.bashrc' '/root/fwall-rules' '/root/.gitconfig' )
    
    echo "Purging..."
    rm -Rf $BACKUP_DIR
    mkdir $BACKUP_DIR
    
    echo "Backup"
    for i in "${files[@]}"
    do
      cp -r $i $BACKUP_DIR
    done
    
  4. Il ne reste qu’à ajouter, commiter et pusher vos éléments sur bitbucket.
    Vous pouvez même ajouter cette ligne dans votre backup.sh, avec un timestamp dans le commentaire du commit…
    Ou créer à chaque commit un tag git, pour retrouver vos versions, etc.

    git commit -a "My backup"

Streams et Node.js : mongoose vers Amazon S3 ou fichier

Mongoose, ODM dont la réputation n’est plus à faire pour s’interfacer avec une base MongoDB, permet de lancer des requêtes sur des milliers de données, et de lire le résultat sous forme de stream.

Rapide rappel sur les Streams Node.js :

Il faut voir les Streams comme des entonnoirs : on peut les imbriquer comme des légos (grâce au pipe).

  • Certains permettent de lire : StreamReader, ils envoient l’eau
  • d’autres d’écrire : StreamWriter, ils récupère l’eau reçue
  • et d’autres sont les 2 à la fois : Duplex et/ou Transform, il reçoivent l’eau, peuvent la nettoyer (Transform) puis la renvoyer

L’entonnoir est imagine qui n’est pas anodine : si on verse de l’eau trop vite dans un entonnoir, elle s’accumule sans avoir le temps de passer. Le parallèle de ce phénomène avec les Streams est ce qu’on appelle la « back pressure« . C’est ce qui se passe le stream qui lit va plus vite que celui qui écrit.

Voyons ça dans un exemple…

Continuer la lecture de Streams et Node.js : mongoose vers Amazon S3 ou fichier 

Aujourd’hui on s’amuse ! Division euclidienne et distribution de graines…

J’avais un algorithme rigolo à faire aujourd’hui : ça revient à distribuer des graines qu’on a dans sa main, dans des petites cases (un peu comme un walé).

Pour économiser de nombreuses boucles ou de la récursivité, solution qui s’avèrerait bien lourde… j’ai cherché un moyen de calculer le nombre de graines à déposer dans les cases, avant même de les déposer, histoire de justement les déposer en une passe (c’est vrai quoi, PHP n’a pas que ça à faire non plus…)

La division euclidienne s’écrit : a = bq + r (a=graines, b=cases, q=quotient, r=reste).
Ex: 3 cases et 5 grainres.
5 = 3×1 + 2
On doit distribuer 1 graine dans chaque case (=quotient), il nous en restera 2, qu’on distribuera au 2 premières.
Pour distribuer ces 2 dernières, on en dépose 1 seule ds chq case, tant qu’il nous en reste.
On peut ainsi calculer d’un coup le nb de graines à déposer dans chaque case,
Pour chaque case : on pose la graine (quotient) et on pioche 1 graine dans le reste tant qu’il en reste.
Ca donne : 2, 2, 1

La fonction utilitaire donne donc ceci (avec un peu de debug quand meme, à adapter à votre sauce) :
Continuer la lecture de Aujourd’hui on s’amuse ! Division euclidienne et distribution de graines… 

Terminal : ouvrez vos onglets via un script bash

Travaillant sur une application SPA , j’ai besoin de démarrer mon environnement chaque matin.

j’ai donc besoin de 3 onglets :

  1. application serveur Node.js (node start)
  2. application cliente (gulp)
  3. Shell MongoDB

Voici donc un script permettant d’ouvrir 3 onglets de terminal et de lancer les commandes respectives dans chaque onglet :

Continuer la lecture de Terminal : ouvrez vos onglets via un script bash 

bUkMzLll_400x400Bonjour à tous, je serai au Drupal Dev Days à Montpellier, du 15 au 17 avril,

c’est top que ce soit si près cette année !

Je serai heureux de vous y rencontrer.

Etienne

Drupal 7 : regénérer sa cron_key en cas de problème

Au secours ! ma cron_key a disparu !!

Dernièrement, ayant des soucis de crons, j’ai suivi des tas de forums disant comment s’en sortir.
Sauf que parmi les manip, j’ai viré toutes les variables commençant par cron_
Donc dedans, il y avait la cron_key !

Des modules existent vous permettant de le faire, mais franchement, pas besoin d’installer tout un module pour le faire

drush php-eval "variable_set('cron_key', drupal_random_key());"

La cron_key sera alors de nouveau renseignée en base, et vous pourrez la récupérer comme d’habitude dans votre back-office, onglet Report (admin/reports/status).

(pour info, vous ne pouvez l’insérer avec un phpMyAdmin facilement, en créant name=cron_key, value=la valeur, car la valeur est un objet PHP sérialisé en fait.

Enjoy !

Validateur asynchrone avec Mongoose

Comment valider un champ de son modèle en asynchrone avant de l’enregistrer ?

Prenons le cas suivant : on a un modèle Mobilhomes et un modèle Marque.  On utilise mongoose pour enregistrer un mobilhome.

Ici, je n’utilise pas les ref dans le schéma, mais on pourrait le faire (cf http://mongoosejs.com/docs/populate.html).

var MobilHomeSchema = Schema({
  _id: Schema.Types.ObjectId,
  marque: {
    _id: Schema.Types.ObjectId,
    lib: String
  }
});

var MarqueSchema = Schema({
  _id: Schema.Types.ObjectId,
  lib: String
});

Le souci est que lorsqu’on enregistre un mobilhome avec un ID de marque « bidon », pour valider que l’ID existe bien et qu’un petit malin ne s’amuse pas à essayer d’enregistrer un ID bidon, on veut valider la donnée.

Il faut donc aller chercher dans la collection Marque, si l’ID existe ou non.

On a créé un validateur « custom » mongoose, qui se déclenche au validate(). Dans ce validateur, on fait un marque.findById(ID_A_VALIDER, callback) => ARGH ! on ne récupère le résultat du findById qu’en asynchrone, dans le callback, trop tard pour le validateur mongoose ! En gros, le validateur aurait besoin de savoir, en synchrone, si l’ID existe ou non….

var MobilHomeSchema = Schema({
  _id: {
      type: Schema.Types.ObjectId,
      validate: myCustomValidatorFunction
  marque: {
    _id: Schema.Types.ObjectId,
    lib: String
  }
});

function myCustomValidatorFunction(val){
   // supposons que Marque soit défini, que ce soit un modèle mongoose
   Marque.findById(val, function(err, item){
     if (err) handleError(err);

     // et là, qu'est-ce qu'on fait ?? on retourne TRUE ou FALSE ?
     // ben non... c'est trop tard...
     // 'suite' a déjà été affiché ! Vive l'asynchrone...

     // le code suivant ne sert évidemment à rien :(
     return (item != null);
   });

   console.log('suite');
}

La solution est donc, comme assez souvent avec l’asynchrone, que la librairie nous a prévu le coup ! Le custom validator peut attendre un second paramètre, qui est un callback que mongoose utilise pour traiter des validateurs asynchrones. Bon c’est écrit noir sur blanc dans la doc, mais ça mérite un petit exemple (http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate) :

function myCustomValidatorFunction(val, respond){
   // supposons que Marque soit défini, que ce soit un modèle mongoose
   Marque.findById(val, function(err, item){
     if (err) handleError(err);

     // ici, on appelle le callback avec un booléen en paramètre, résultat de notre validateur
     respond(item != null);
   });
}

D’Angular.js à Backbone.js… le retour

Il y a quelques temps, j’avais écrit un article sur les frameworks JS clients, pour réaliser des applications mono-page (SPA).
Mon choix s’orientait alors plutôt vers Angular.js, après l’avoir testé, ainsi que Ember et Backbone.

Depuis la création de cette article, pas mal d’eau à couler sous le pont de mes essais, et j’avoue revenir vers Backbone.js finalement !

Pourquoi ?
Tout d’abord, entre temps j’avais réalisé mon propotype en Angular.js pour comparer. Seulement, bien que plus simple quand on commence (un certain nombre de choses fonctionnent sans avoir à les coder sois-même : binding des events entre vue et controlleur, etc.), on se rend compte petit à petit que c’est pas forcément le cas quand on dépasse le simple cas d’école, qu’il vaut mieux faire des directives plutôt que d’utiliser des composants natifs (comme pour bootstrap widgets par ex), qu’on est finalement pieds et poings liés au fonctionnement d’Angular. Backbone.js offre beaucoup plus de liberté, puisqu’il est très bas niveau. Il offre des briques avec lesquelles composer, mais finalement c’est toujours la même logique, très simple, bien qu’assez verbeuse.
De plus, en approfondissant le sujet, la verbosité de Backbone peut s’améliorer nettement en ajoutant une surcouche comme Marionette.js

De plus, autre argument non négligeable : Angular est une techno Google, soit disant open-source, mais la seule communauté travaillant sur ce dit  code est… Google ! Et les technos Google sont parfois éphémères.

Bon et pour finir, j’ai aussi été formé entre temps sur Node.js (par Christophe Porteneuve, allez-y les yeux fermés, c’est génialissime ! ), on a pu également échanger sur les frameworks JS pour les SPA, ce qui m’a aussi influencer dans mon choix de Backbone.js. Ca a nettement améliorer ma vision d’ensemble de comment articuler toutes ces briques : serveur, API REST, client, offline first, …

Je commence une application (une vraie, pas un proto cette fois !) en Node.js pour le côté serveur REST, et en Backbone.js/Marionette.js pour le côté client.
Je compte donc vous écrire un petit article là-dessus prochainement !

A bientôt  !

 

Installer Node.js via nvm (permet de le multi-versions)

Vous pouvez installer une version fixe de node, mais ça devient vite pénible de le mettre à jour, et si vous devez utiliser plusieurs versions selon les projets, n’en parlons pas…

Bref, nvm est là pour ça, il permet d’installer différentes versions et de basculer de l’une à l’autre par une simple ligne de commande.

Continuer la lecture de Installer Node.js via nvm (permet de le multi-versions)