Introduction aux pipelines

Il vous est peut-être arri­vé d'attendre qu'un logi­ciel A ait fini son tra­vail pour pou­voir lan­cer un logi­ciel B, qui lui uti­lise la sor­tie du logi­ciel A. Si l'exécution de A ne prend que quelques secondes cela n'est pas trop grave. Par contre, si elle prend des heures et que vous devez véri­fier régu­liè­re­ment s’il a fini, cela peut très vite deve­nir fati­gant. Une bonne solu­tion serait de faire que le logi­ciel B s'exécute auto­ma­ti­que­ment quand A a fini et c'est cela que l'on appelle un pipe­line. Aujourd'hui je vais éclair­cir pour vous ce terme et don­ner quelque exemples, très simples, de pipe­lines sous GNU/​Linux.

C'est quoi un pipe­line ?

Il s'agit d'un terme anglais, en infor­ma­tique il désigne un groupe de logi­ciels exé­cu­tés en série de telle façon que la sor­tie d'un logi­ciel sert d'entrée pour le sui­vant. Il y a dif­fé­rents inté­rêts à la construc­tion d'un pipe­line. On peut par exemple cher­cher à exé­cu­ter à la chaîne une série de logi­ciels pou­vant écrire sur la sor­tie stan­dard et ain­si évi­ter de créer des fichiers inter­mé­diaires. On peut éga­le­ment cher­cher à ce que toute une série de tâches s'exécutent les unes après les autres, sans inter­ven­tion de l'utilisateur.

Dans sa forme la plus simple, le pipe­line n'est qu'une chaîne où chaque logi­ciel attend la sor­tie du pré­cé­dent, mais on peut construire des pipe­lines où plu­sieurs logi­ciels dépendent de la sor­tie d'un autre et vice-ver­sa (cf. Shé­ma). Cer­tains pipe­lines contiennent même des boucles pour véri­fier si la com­mande pré­cé­dente s'est bien exé­cu­tée, et si se n'est pas le cas, la relan­cer au lieu de lan­cer le logi­ciel sui­vant. La com­plexi­té aug­mente, bien sûr, avec le nombre d'étapes dans le pipe­line et le nombre de connexions entre elles.

Pour illus­trer la notion de pipe­line, je vais vous pré­sen­ter quelque exemples qui pour­ront vous ser­vir pour des petites tâches de la vie de tous les jours (enfin, celle des bio-infor­ma­ti­ciens).

 

Les logi­ciels 2 et 3 attendent le résul­tat du logi­ciel 1. Le logi­ciel 4 lui ,uti­lise les sor­ties des logi­ciels 2 et 3.

Pre­mier pipe­line sur sor­tie stan­dard

Sous GNU/​Linux il existe une façon très simple de faire un pipe­line, en ligne de com­mande, avec le sym­bole pipe '|'.

Voi­ci un petit exemple : dans un ter­mi­nal, on peut recher­cher une com­mande que l'on a tapée pré­cé­dem­ment avec à la com­mande 'his­to­ry', mais elle résume par­fois des mil­liers de com­mandes et si celle que vous cher­chez est la mil­lième cela peut être dif­fi­cile de la trou­ver. Du coup il serait bien de pou­voir cher­cher notre com­mande grâce à un mot qu'elle contient. On peut le faire avec la com­mande 'grep', qui per­met de cher­cher un terme spé­ci­fique dans un texte et d'afficher la ou les lignes qui le contiennent. Un moyen simple de connec­ter ces deux com­mandes est d'utiliser le pipe et de construire notre pre­mier pipe­line.

Dans cet exemple, je recherche les com­mandes que j'ai uti­li­sées avec le logi­ciel 'sam­tools':

$history | grep samtools
844 bsub -M6000000 'samtools view -Sb test_all.VIR.sam -o test_all.VIR.bam'
870 bsub -M6000000 'samtools sort test_all.VIR.bam test_all.VIR_sorted'

 

Comme vous pou­vez le voir, le chiffre en début de ligne indique la posi­tion où se trou­vait chaque com­mande, je n'avais pas uti­li­sé sam­tools depuis un petit moment et j'aurais eu de la peine à retrou­ver ma com­mande sans ce petit pipe­line.

Une autre façon d'utiliser la sor­tie stan­dard est de faire appel à la com­mande 'xargs'. Ima­gi­nons cette fois que je cherche un fichier et dont je veux affi­cher le début. Je peux uti­li­ser la fonc­tion 'find' pour trou­ver mon fichier et 'head' pour en affi­cher le début.

Essayons avec le pipe :

$ find . -name info.csv
./test/info.csv

$find . -name info.csv | head
./test/info.csv

Et mince, 'head' imprime ici le début du résul­tat de notre com­mande 'find' et non pas le début du fichier. Il faut donc une méthode pour faire com­prendre à 'head' que les infor­ma­tion qu'on lui envoie doivent être uti­li­sées comme argu­ment et non pas comme simple texte. Uti­li­sons xargs pour résoudre ce pro­blème.

$find . -name info.csv | xargs head
Ceci est la première et dernière ligne du fichier info.

Et voi­là pro­blème réso­lu, la com­mande 'find' trouve mon fichier et la com­mande 'head' affiche les pre­mières lignes. Si il y avait eu plu­sieurs fichiers, cha­cun d'entre eux aurait été envoyé à la com­mande 'head' et leurs débuts auraient été impri­més les uns à la suite des autres.

(Pour les plus curieux, on peut le faire aus­si avec l'option '-exec' de la com­mande find, mais dans ce cas pas besoin de pipe­line)

 

Pipe­line avec fichiers inter­mé­diaires

Les deux exemples pré­cé­dents uti­li­saient la sor­tie stan­dard com­ment entrée pour la com­mande sui­vante. Je vais main­te­nant vous mon­trer com­ment enchaî­ner deux com­mandes et uti­li­ser un fichier créé par la pre­mière.

Dans votre ter­mi­nal c'est en fait très simple, il suf­fit d'écrire les deux com­mandes sur une seule ligne, mais en les séparent avec un point-vir­gule.

Voi­ci un petit exemple avec les com­mandes sam­tools que j'ai cher­chées dans le pre­mier exemple :

samtools view -Sb test_all.VIR.sam -o test_all.VIR.bam

samtools sort test_all.VIR.bam test_all.VIR_sorted

La pre­mière com­mande crée le fichier 'test_all.VIR.bam' et la deuxième le trie. Pour mettre un petit contrôle on peut par exemple écrire dans un fichier que la com­mande est ter­mi­née. Ici ce n'est pas bien impor­tant, mais ima­gi­nez-vous ali­gner six ou sept com­mandes pour com­prendre l'importance de ce rap­port d'exécution. En effet si une com­mande ren­contre une erreur, alors toutes les sui­vantes ne seront pas exé­cu­tées.

$samtools view -Sb test_all.VIR.sam -o test_all.VIR.bam; echo 'commande 1 terminee' > rapport_execution.txt; samtools sort test_all.VIR.bam test_all.VIR_sorted; echo 'commande 2 terminee' >> rapport_execution.txt

Et voi­là, les com­mandes vont s'exécuter les unes après les autres et si quelque chose se passe mal, je sau­rai à quel niveau, grâce à mon fichier de contrôle.


Les méthodes pré­sen­tées dans cet article ne vous ser­vi­ront pas pour construire un pipe­line robuste, qui exé­cute à la suite toute l'analyse de vos don­nées de séquen­çage. Vous pou­vez uti­li­ser pour cela des logi­ciels tel que Galaxy, déjà pré­sen­té sur le blog (Galaxy ). Mais il existe de nom­breuses méthodes et je pré­sen­te­rai dans un pro­chain article com­ment uti­li­ser le sys­tème de queue d'un clus­ter pour construire un pipe­line plus com­plexe.

En atten­dant n'hésitez pas à faire part des méthodes que vous uti­li­sez dans les com­men­taires et si l'envie vous en prend, faites un article et pro­po­sez-le aux admins, nous sommes tou­jours contents d'avoir de nou­velles méthodes à partager/​publier.

Je tiens à remer­cier Yoann, Nol­wenn et Nel­ly pour leur relec­ture.



Pour continuer la lecture :


Commentaires

6 réponses à “Introduction aux pipelines”

  1. Les pipe­lines sont des élé­ments essen­tiels dans notre tra­vail de tous les jours. Très bonne astuce pour conser­ver une trace des com­mandes exé­cu­tées.

    Mer­ci

  2. J'ajouterais deux choses à cette articles si vous me le per­met­tez :
    — l'utilisation de && en lieu et place des ; dans votre exemple per­met­trons de contrô­ler la bonne exé­cu­tion de la com­mande pré­cé­dente ($? == 0). Du coup, je pipe­line s'arrête quand il ren­contre une erreur sans lan­cer la suite (qui sou­vent en dépende)
    — la com­mande tee per­met quant à elle de redi­ri­ger la stout de la com­mande pré­cé­dente dans un fichier et dans le stdin de la com­mande sui­vant. Cela per­met de créer faci­le­ment des fichiers inter­mé­diaires sans "cas­ser" le pipe­line.

    GLC

    1. Mer­ci se sont d'exellent conseils.

      En effet dans mon exemple avec sam­tools, si la pre­mière com­mande ne fonc­tionne pas, la sui­vante va être lan­cé mais ne trou­ve­ra pas le fichier .bam. Il faut donc rem­pla­cer les ';' par '&&'. De plus cela aurait écrit dans le rap­port que les 1 et 2 étaient ter­mi­nées, ce qui est faux dans ce cas.

      Pour 'tee', je ne l'avais jamais uti­li­sé, mais c'est effec­ti­ve­ment très sym­pa.

      Pour les lec­teurs, disont que dans le pre­mier exemple, en plus d'afficher les com­mandes qui contiennent le mot 'sam­tools' je veux sau­ver mon his­to­rique dans un fichier, le tout en un seul pipe­line, je peux le faire grace à 'tee'.

      $his­to­ry | tee mon_historique.txt | grep 'sam­tools'
      844 bsub ‑M6000000 'sam­tools view ‑Sb test_all.VIR.sam ‑o test_all.VIR.bam'
      870 bsub ‑M6000000 'sam­tools sort test_all.VIR.bam test_all.VIR_sorted'

      $head ‑3 mon_historique.txt #com­mande qui affiche le début du fichier
      26 mkdir bamToFastq_​test
      27 cd bamToFastq_​test/​
      35 bsub 'gun­zip *.gz'

      Voi­la, le résul­tat affi­ché est le même, mai sj'ai en plus une sau­ve­garde de mon his­to­rique. Je vous laisse ima­gi­ner toutes les appli­ca­tions pos­sibles.

      Mer­ci pour ses conseils, j'espère que d'autres lec­teurs pren­dront le temps de nous don­ner ce genre d'informations.

      Ismael

  3. Très bon article qui montre l'un des aspect les plus inté­res­sant du shell.
    Je ne connais­sais pas la com­mande tee qui est plu­tôt inté­res­sante, mer­ci pour cette décou­verte.

    Par contre je pré­fère redi­ri­gé stderr dans un fichier de log avec '2>>fichier.log' plu­tôt que d'afficher un simple mes­sage de fin d'exécution.

    $sam­tools view ‑Sb test_all.VIR.sam ‑o test_all.VIR.bam 2>>rapport_execution.txt && sam­tools sort test_all.VIR.bam test_all.VIR_sorted 2>>rapport_execution.txt

    Ça per­met d'avoir une trace com­plète des erreurs éven­tuelles.

  4. Avatar de LEPENNETIER Gildas
    LEPENNETIER Gildas

    J'y connait pas grand chose, mais mettre le tout dans un fichier .sh et l’appeler avc bash per­met aus­si un pipe­line effi­cace, avec en plus la ges­tion de variables. L'avantage c'est qu'on garde une trace, le désa­van­tage c'est que ça peut faire beau­coup de fichier au finale.

  5. Avatar de Lansana
    Lansana

    article inter­es­sant.… mer­ci.
    La com­mande 'tee' est aus­si vrai­ment sym­pa.

Laisser un commentaire