Créez vos propres périphériques

Gazette Linux n°114 — Mai 2005

Jean-Baka Domelevo-Entfellner

Adaptation française

Joëlle Cornavin

Relecture de la version française

Article paru dans le n°114 de la Gazette Linux de mai 2005.

Article publié sous Open Publication License. La Linux Gazette n'est ni produite, ni sponsorisée, ni avalisée par notre hébergeur principal, SSC, Inc.


Table des matières

1. Introduction
2. Comment « faire semblant » avec une boucle
3. Entrez dans mon salon...
4. Instantanées et copies-sur-écriture (COW, Copy-on-Write)
5. Seulement pour vos yeux
6. Allons à la racine du problème
7. Conclusion

1. Introduction

Linux 2.4.x avait le LVM (Logical Volume Manager, gestionnaire de volumes logiques) et d'autres constructs de périphériques blocs multidisques ou multipartitions. Ceux-ci ont été améliorés par le mappeur de périphériques (device mapper) dans Linux 2.6.x. En voici le résumé en une ligne :

Vous pouvez choisir n'importe quelle séquence de blocs sur une séquence de périphériques blocs et créer un nouveau périphérique bloc dont certains des blocs sont identifiés avec les blocs que vous avez choisis auparavant.

Cette opération prendra un certain temps. En attendant, voici quelques façons d'utiliser le mappeur de périphériques :

  • Quels fichiers ce programme créera-t-il ? Écrivez-les sur un disque en mode copie-sur-écriture (COW, Copy-On-Write) !

  • Ne laissez pas le système de fichiers partir en vacances lorsque vous prenez des instantanés.

  • Coupez-le en dés, en tranches, redimensionnez-le — mais ne réamorcez pas.

  • Si vos données valent plus que votre disque dur, chiffrez-les.

Il y a une contrepartie, naturellement. Pour faire tout cela avec le périphérique racine (root), certains changements sont nécessaires au moment de l'amorçage. Plutôt que de nous éparpiller, nous nous concentrerons sur l'apprentissage du mappeur de périphériques — à cette fin, nous utiliserons des périphériques boucles « factices » (loop devices) au lieu de disques « réels ». Quand vous aurez pris de l'assurance, vous pourrez passer aux disques réels, voire à la partition racine.

2. Comment « faire semblant » avec une boucle

Sous Unix, tout est fichier. Même un périphérique bloc comme /dev/hda2, qui est censé être lu par « morceaux » appelés blocs, peut être lu octet par octet, comme un fichier. Le périphérique boucle (loop device) nous permet d'inverser cette asymétrie et de considérer n'importe quel fichier comme un périphérique bloc. Activez les périphériques boucle pour votre noyau Linux avec modprobe boucle (en tant que root) si nécessaire.

Pour le démontrer sans risquer d'endommager gravement des fichiers utiles, nous n'utiliserons que des fichiers vides. Tout d'abord, créez un fichier vide comme suit :


dd if=/dev/zero of=/tmp/enregistrement1 bs=1024 seek=2047 count=1

Cette commande crée un fichier plein de vide d'une taille de 2 Mo. Transformons-le maintenant en périphérique bloc :


losetup /dev/boucle1 /tmp/enregistrement1

Nous employons ensuite ce périphérique bloc comme nous le ferions avec tout autre périphérique bloc :

  1. Vérifiez sa taille exprimée en blocs de 512 octets :

    
    blockdev --getsize /dev/boucle1
    
    

  2. Créez un système de fichiers sur celui-ci :

    
    mke2fs /dev/boucle1
    
    

  3. Montez ce système de fichiers dans un endroit quelconque :

    
    mount /dev/boucle1 /mnt
    
    

Vous pouvez ensuite utiliser /mnt exactement de la même manière que tout autre système de fichiers. Les changements seront écrits dans /tmp/enregistrement1. Lorsque vous en avez assez de jouer avec les blocs en boucle, débarrassez-vous en avec une commande comme losetup -d /dev/boucle1.

Dans ce qui suit, nous utiliserons des périphériques boucles comme /dev/boucle1, /dev/boucle2/, etc. à titre de briques de base de nos périphériques blocs.

3. Entrez dans mon salon...

... dit le mappeur de périphériques au périphérique bloc. S'il n'est pas déjà activé, chargez le mappeur de périphériques correspondant à votre noyau Linux avec la commande modprobe dm-mod (en tant que root). Le mappeur de périphériques peut prendre sous son aile n'importe quel périphérique bloc avec une commande comme :


echo 0 $(blockdev --getsize /dev/boucle1) linear /dev/boucle1 0 | \
    dmsetup create nouveau

Cette commande crée un « nouveau » périphérique bloc /dev/mapper/nouveau, mais ce ne sont pas vraiment de nouvelles données. Lire à partir de cette unité de blocs donne exactement le même résulat que lire directement depuis /dev/boucle1. Il en va de même en ce qui concerne l'écriture sur ce périphérique bloc. Ainsi, vous pouvez vous débarrasser de ce périphérique bloc à l'aide de la commande dmsetup remove nouveau.

Bien sûr, vous pouvez procéder différemment. Par exemple, vous pouvez ne prendre que la moitié de /dev/boucle1 en tant que périphérique bloc :


SIZE1=$(blockdev --getsize /dev/boucle1)
echo 0 $(($SIZE1 / 2)) linear /devboucle1 0 | \
    dmsetup create un-demi

La moitié restante (qui pourrait être la plus grosse si /dev/boucle1 contient un nombre impair d'octets !) est alors toujours disponible pour un autre usage. Vous pourriez par exemple l'employer en combinaison avec /dev/boucle2 pour créer un autre périphérique bloc :


REST1=$((SIZE1 - $SIZE1 / 2))
echo 0 $REST1 linear /dev/boucle1 $((SIZE1 / 2))  > /tmp/table1
echo $REST1 $(blockdev --getsize /dev/boucle2) \
    linear /dev/boucle2 0 >> /tmp/table1
dmsetup create un-et-demi /tmp/table1

Essayons de comprendre cet exemple et la signification de chacun des trois nombres qui apparaissent sur chaque ligne du fichier /tmp/table. Le premier nombre est le secteur de démarrage de la correspondance décrite, le deuxième est le nombre de secteurs dans la correspondance. Le mot linear est suivi du nom du périphérique d'origine auquel se réfère la correspondance. Vient ensuite le numéro de secteur du premier secteur (de ce périphérique d'origine) qui est affecté par cette correspondance. Relisez cela encore une fois !

Ainsi, vous pouvez découper et recomposer vos disques à l'envi, mais il y a un léger coût, évidemment. Toutes les opérations effectuées sur ces nouveaux périphériques bloc passent au travers du mappeur de périphériques plutôt que de se rendre directement dans le matériel sous-jacent. Avec une gestion efficace des tables dans le noyau, ce surcoût ne devrait pas ralentir les choses de façon perceptible.

Notez comment j'ai (habilement, n'est-ce pas ?) introduit le sujet sur l'utilisation des « tables » qui contiennent la description des périphériques mis en correspondance. Si vous envisagez de beaucoup utiliser les périphériques mis en correspondance et ne voulez pas oublier vos paramètres, vous ne ferez pas l'économie de telles tables. Ne vous inquiétez pas — vous pouvez toujours obtenir la table d'un périphérique quelconque comme /dev/mapper/nouveau par la commande suivante :


dmsetup table nouveau

Dans la sortie, comme le périphérique bloc d'origine apparaîtra sous la forme majeur:mineur, vous devrez découvrir quel est le périphérique effectivement appelé si vous avez besoin de cette table dans un format humainement lisible.

Astuce

Essayez la commande suivante (ou quelque chose d'approchant) :


ls -l /dev | grep "$majeur, *$mineur"

Quand vous avez fini, n'oubliez pas d'exécuter la commande suivante :


dmsetup remove un-demi
dmsetup remove un-et-demi

Peut-être êtes-vous l'une de ces personnes qui ont plusieurs disques configurés, de sorte qu'il est plus lent de lire n octets à partir de l'un d'entre eux que de lire n/2 octets à partir de deux d'entre eux. Cela peut arriver parce que votre contrôleur de disque est capable de réaliser des opérations sur plusieurs disques en parallèle ou bien parce que vous avez plusieurs contrôleurs de disque. Le mappeur de périphériques peut vous aider à accélérer vos opérations :


SIZE=$(( $(blockdev --getsize /dev/boucle1) + \
$(blockdev --getsize /dev/boucle2) ))
echo 0 $SIZE striped 2 16 /dev/boucle1 0 /dev/boucle2 0 | \
    dmsetup create tigre

Dorénavant, les lectures/écritures depuis /dev/mapper/tigre se succéderont (par blocs de 16 secteurs) entre les deux périphériques. Vous aurez de plus combiné les deux disques en un seul comme dans le cas avec linear.

4. Instantanées et copies-sur-écriture (COW, Copy-on-Write)

Un certain nombre de raisons peuvent vous amener à interrompre toutes les opérations d'écriture sur votre périphérique bloc, sans que votre système ne s'arrête définitivement.

Sauvegardes régulières

Il fut un temps où les machines étaient placées en mode mono-utilisateur le temps d'effectuer des sauvegardes. Toutefois, sauvegarder un système « vivant » présente le risque d'avoir des fichiers incomplets ou corrompus, voire des pointeurs temporels erronés.

Sécurité

Vous voulez installer cet économiseur d'écran aux couleurs vives. Quels changements va-t-il faire subir à votre système de fichiers ? Vous voulez savoir.

Cédéroms

... et autres périphériques physiques en lecture seule. Supposons que vous vouliez installer votre système sur un cédérom, tout en autorisant néanmoins des changements locaux « éphémères » qui sont abandonnés lorsque le système redémarre.

La solution réside dans la redirection. En pratique, vous indiquez aux processus « Regardez derrière vous ! » et, en un clin d'œil, vous rajoutez une couche entre le processus et le périphérique. Activez la fonctionnalité d'instantané du mappeur de périphériques avec modprobe dm-snapshot si nécessaire.

Commençons alors avec un périphérique géré par le mappeur de périphériques. Il pourrait par exemple être créé par les commandes suivantes :


SIZE1=$(blockdev --getsize /dev/boucle1)
SIZE2=$(blockdev --getsize /dev/boucle1)
cat > /tmp/table2 <<EOF
0 $SIZE1 linear /dev/boucle1 0
$SIZE1 $SIZE2 linear /dev/boucle2 0
EOF
dmsetup create base /tmp/table21

Supposons maintenant que vous ayez placé un système de fichiers sur ce périphérique avec une commande comme mke2fs /dev/mapper/base et que vous ayez commencé à utiliser ce système de fichiers au point de montage /mnt avec la commande mount /dev/mapper/base /mnt .

Prenons à présent un « instantané » de ce système de fichiers — au ralenti ! Les étapes suivantes doivent être effectuées assez rapidement (par exemple avec un script) sur un système qui tourne et où les changements sur le système de fichiers sont fréquents.

Avant tout, créez une copie de ce disque. Ce n'est pas seulement pour des raisons de sécurité, puisque nous allons changer la signification de /dev/mapper/base sans en avertir le système de fichiers :


dmsetup table base | dmsetup create base

Préparons ensuite notre périphérique bloc en copie-sur-écriture en nous assurant que les huit premiers secteurs (ou toute autre valeur que vous choisirez comme étant la taille de vos blocs) sont remplis de zéros :


CHUNK=8
dd if=/dev/zero of=/dev/boucle3 bs=512 count=$CHUNK

Maintenant, nous suspendons toutes les opérations d'E/S (lecture/écriture) sur le périphérique base. C'est l'étape critique pour tout système actif. Le noyau devra mettre en sommeil[1] tous les processus qui tentent de lire depuis, ou écrire vers, ce périphérique. Nous voulons donc être sûrs de pouvoir reprendre ces opérations rapidement :


dmsetup suspend base && DATE=$(date)

L'étape suivante consiste à utiliser la copie-sur-écriture pour cloner le périphérique :


echo 0 $(blockdev --getsize /dev/mapper/basedup) \
snapshot /dev/mapper/base /dev/boucle3 p 8 | \
    dmsetup create top

Ces lignes signifient qu'à partir de maintenant, un accès en lecture depuis /dev/mapper/top renverra les données provenant de /dev/mapper/basedup, à moins que vous n'écriviez « par-dessus » les données d'origine. Les accès en écriture sur top seront en fait réalisés sur /dev/boucle3 par blocs d'une taille de 8 secteurs. L'effet est le même que si vous utilisiez plusieurs feuilles de plastique transparent superposées (appelées « calques » dans Gimp) ‐ ce qui est écrit par-dessus occulte ce qui est au-dessous, mais là où rien n'est écrit par-dessus, vous voyez clairement ce qu'il y a sur la feuille du dessous.

En particulier, nous pouvons maintenant nous assurer que tous les changements apportés aux périphériques blocs sous-jacents sont « volatils ». Si nous exécutons les commandes suivantes (par la suite, nous ferons référence à ce point en tant que 'point A') :


dmsetup table top | dmsetup load base
dmsetup resume base

nous aurons remplacé le système de fichiers situé sous /mnt par un autre, où tous les changements s'insèrent en fait dans /dev/boucle3. Lorsque nous démontons cette configuration, /dev/boucle1 et /dev/boucle2 seront exactement dans l'état où ils étaient à la date $DATE.

Si /dev/boucle1 et /dev/boucle2 sont sur des supports physiques non inscriptibles (par exemple un cédérom), alors que /dev/boucle3 est sur un support inscriptible (par exemple une mémoire vive ou un disque dur), alors nous avons créé un système de fichiers inscriptible à partir d'un autre en lecture seule !

Ceci répond au dernier problème de notre liste ci-dessus. Mais quid des deux premiers ? Pour traiter le deuxième problème, nous devons disposer d'un moyen quelconque pour comparer le nouveau système de fichiers avec l'ancien. Si pour ce faire, vous essayez de monter /dev/mapperbasedup quelque part, vous constaterez que Linux (le noyau !) vous l'interdit. À la place, nous pouvons créer encore un autre périphérique :


echo 0 $(blockdev --getsize /dev/mapper/basedup) \
    snapshot-origin /dev/mapper/basedup | \
    dmsetup create originel

Vous pouvez maintenant monter /dev/mapper/originel quelque part (par exemple /tmp/orig) et comparer le système de fichiers originel avec l'actuel à l'aide d'une commande comme :


diff -qur /tmp/orig /mnt

Que se passe-t-il si vous écrivez sur /tmp/orig ? Vérifiez, et vous n'en reviendrez pas.

L'analogie avec les transparents s'arrête ici ! Tous les accès en écriture sur /tmp/orig vont directement vers le périphérique sous-jacent basedup mais sont niés sur /dev/boucle3, de telle sorte qu'ils deviennent invisibles aux lectures depuis /mnt. De la même manière, les opérations de lecture depuis /tmp/orig ignorent tout changement apporté par une écriture sur /mnt. En d'autres termes, le système de fichiers originel a été « copié » (forked), orthogonalement, qui plus est ! et /dev/boucle3 qui en fait stocke à la fois les données en positif et en négatif. Impossible de créer un transparent qui fonctionne ainsi !

Pour vérifier l'utilité de ce comportement, regardons comment il résoud le problème des sauvegardes. Ce que nous voulons, c'est obtenir un « instantané » du système de fichiers, tout en continuant à utiliser le système de fichiers originel. Dans ce cas, nous ne devrons donc pas exécuter les commandes au point A ci-dessus. À la place, exécutons les commandes suivantes ici, au point B :


dmsetup table originel | dmsetup load base
dmsetup resume base

Désormais, tous les accès en écriture sur /mnt vont vers le périphérique originel, mais ces changements sont niés sur /dev/mapper/top. Donc, si nous montons ce dernier sur, par exemple /tmp/snap, alors nous pouvons lire un instantané des fichiers à l'heure $HEURE depuis ce répertoire. Une commande comme :


cd /tmp/snap
find . -xdev | cpio -o -H nouveau > "sauvegarde-$HEURE"

fournira une sauvegarde de l'instantané du système de fichiers à l'heure $HEURE.

Nous aurions aussi pu prendre un instantané au point A avec les commandes :


cd /tmp/orig
find . -xdev | cpio -o -H nouveau > "sauvegarde-$HEURE"

La principale différence est que les changements apportés à /dev/mapper/top sont volatils ! Il n'y a aucun moyen de démonter facilement la structure créée au (A) sans perdre toutes les changements effectués. Dans le contexte d'une sauvegarde, vous voulez retenir les changements. Au point B, exécutez :


dmsetup suspend base
dmsetup remove top
dmsetup remove originel
dmsetup table basedup | dmsetup load base
dmsetup resume base

et vous pouvez reprendre votre travail comme d'habitude. Si vous le faisiez au point A, les résultats seraient complètement imprévisibles ! Quel serait l'état de tous ces fichiers ouverts sur /dev/mapper/top ? Un certain nombre de processus seraient très probablement suspendus — il se pourrait même que certains threads du noyau se bloquent — et même « plantent » !

5. Seulement pour vos yeux

Supposons que vous ayez un ordinateur portable ou un cédrom qui contient des données importantes, non seulement à vos yeux mais pour quiconque les détient. Dans ce cas, des sauvegardes ne sont pas souhaitables. Ce que vous voulez, c'est protéger ces données contre le vol. En partant du principe que vous croyez en la robustesse des techniques de chiffrement actuelles, vous pourriez les protéger en chiffrant le fichier en question. Cette approche présente de graves défauts :

  • Le fichier doit être déchiffré/rechiffré chaque fois que vous voulez vous en servir.

  • Le fichier chiffré se singularise trop, facilitant ainsi les recherches de quiconque voudrait voler vos donnés.

  • Il se peut que vous ne sachiez pas précisément quels fichiers contiennent des données secrètes. Par exemple, vous préparez un rapport confidentiel et vous l'envoyez vers l'imprimante. Pour ce faire, un fichier PDF temporaire a été créé à votre insu et vous ne l'avez pas chiffré.

Pour ces raisons et pour tant d'autres, vous pourriez être amené à chiffrer la totalité du périphérique bloc. Le mappeur de périphériques offre un moyen de le faire. Activez le service de chiffrement du mappeur de périphériques avec modprobe dm-crypt si nécessaire. Si besoin est, activez également certains mécanismes de chiffrement et de hachage avec des commandes comme modprobe md5 ou encore modprobe aes.

Tout d'abord, vous devez générer et enregistrer votre clef secrète. Si vous faites appel à AES (Advanced Encryption Standard) comme indiqué ci-dessus, vous pouvez utiliser une clef d'une longueur allant jusqu'à 32 bits. Pour pouvoir la générer, saisissez par exemple :


dd if=/dev/random bs=16 count=1 | \
  od --width=16 -t x2 | head -1 | \
  cut -f2- -d' ' | tr -d ' ' > /tmp/ma_clef_secrète

Naturellement, vous ne devrez certainement pas écrire votre clef secrète dans un tel fichier — il y a des moyens plus sûrs pour l'enregistrer :

  • Affichez-la directement à l'écran et efforcez-vous de la retenir ! Après tout, ce ne sont que de trente-deux caractères !).

  • Écrivez-la sur une clé USB ou tout autre périphérique de stockage qui ne quittera jamais votre poche.

  • Chiffrez-la à l'aide de gpg (GnuPG) ou d'openssl (Secure Sockets Layer) pour l'enregistrer ensuite sur une clé USB ou tout autre mémoire que vous gardez toujours sur vous.

Si vous choisissez la troisième option, vous devrez utiliser une phrase de passe — vous devrez la retenir également. Un bon moyen de s'en rappeler est de l'utiliser souvent : utilisez-la... ou prenez le risque de l'oublier !

Configurez à présent le périphérique chiffré :


echo 0 $(blockdev --getsize /dev/boucle1) \
   crypt aes-plain $(cat /tmp/ma_clef_secrète) 0 /dev/lboucle1 0 | \
   dmsetup create mes-données

Créez ensuite un système de fichiers mke2fs /dev/mapper/mes-donnees sur ce périphérique bloc et stockez-y des données après l'avoir monté quelque part avec mount /dev/mapper/mes-donnees /mnt. Toutes les données écrites sur /mnt seront chiffrées de façon transparente avant stockage sur /dev/boucle1. Quand vous avez fini, démontez le périphérique et désinstallez-le comme précédemment :


umount /mnt
dmsetup remove mes-donnees

La prochaine fois que vous voudrez utiliser ce périphérique, vous pourrez l'installer avec les mêmes commandes que ci-dessus, sous réserve de fournir la clef secrète dans /tmp/ma-clef-secrete. Bien sûr, vous ne devrez pas exécuter mke2fs une seconde fois, à moins de vouloir effacer toutes ces précieuses données !

6. Allons à la racine du problème

Vous pouvez réaliser toutes les étapes décrites ci-dessus sur n'importe quel(s) périphérique(s) bloc(s), à la place des périphériques boucle (loop devices) que nous avons fait intervenir. Cependant, quand le périphérique en question est la partition racine, les choses se compliquent un peu (les racines sont généralement complexes).

Avant tout, nous devons placer le périphérique racine sous le contrôle du mappeur de périphériques. La meilleure façon de procéder est de faire appel à un disque virtuel (RAM disk) initial (ou initrd). Même après cela, la prudence s'impose si nous essayons d'exécuter une des commandes ci-dessus sur la partition racine d'un système « actif ». En particulier, il n'est pas recommandé de suspendre les entrées/sorties sur le système de fichiers sur le fichier racine sans une profonde introspection préalable ! Quoi qu'il en soit, cela signifie que tous les processus qui créent un appel en lecture/écriture sur le système de fichiers racine seront mis en sommeil.

Voici un moyen de contourner cette difficulté. Créez un système de fichiers temporaire :


mount -t tmpfs tmpfs /mnt

Sur ce système de fichiers, copiez ensuite tous les fichiers nécessaires afin d'effectuer les changements. En particulier, vous aurez besoin de /sbin/dmsetup, de /bin/sh, des fichiers /dev ainsi que de toutes les bibliothèques partagées dont dépendent ces programmes. Exécutez ensuite chroot /mnt. Après quoi vous pourrez lancer un script ou bien (à condition que vous tapiez rapidement et sans fautes !) une suite de commandes qui suspendront la liaison avec la racine et exécuteront les opérations souhaitées, par exemple en prenant un instantané du disque. N'oubliez pas de remettre en route la partition racine avant de sortir du chroot.

7. Conclusion

Compte tenu de la complexité des différentes opérations, la meilleure solution est probablement d'écrire un script shell ou même un programme C qui réaliserait lesdites opérations. Fort heureusement, la seconde solution a déjà été implémentée, puisque le Gestionnaire de Volumes Logiques version 2 (LVM2) réalise effectivement la plupart des tâches décrites ci-dessus de manière assez « automagique ». La mise en place et l'utilisation du chiffrement se trouve grandement simplifiée par l'utilisation du programme cryptsetup. Mais alors pourquoi ai-je donc écrit cet article ?

Au début, je suis tombé sur dmsetup alors que j'essayais de créer un système de fichier racine en lecture seule, pour un « live CD ». Malheureusement, les outils LVM2 ne sont alors d'aucune utilité puisqu'ils ne sont là que pour l'utilisation d'instantanés à des fins de sauvegarde (clairement, il n'ont que faire des systèmes de copie-sur-écriture) ! La seule ressource que j'ai trouvé à ce sujet se trouve dans les archives de la liste de diffusion RedHat. On trouve aujourd'hui des outils fournis avec des « live CD » qui font usage de dmsetup ; par exemple je suis tombé sur ce lien, qui explique comment cela marche chez Ubuntu.

Et bien sûr, l'utilisation de dmsetup m'a permis d'aller « aussi près que possible » du matériel sans toutefois écrire de vrais programmes...

Kapil Hari Paranjape a l'âme d'un « hacker » depuis l'époque des cartes perforées. Plus précisément, cela veut dire qu'il n'a jamais écrit de « véritable » programme. Il s'est contenté d'expérimenter des programmes écrits par d'autres. Après avoir joué avec Minix en 1990-91, il a pensé écrire son premier logiciel — un « authentique » noyau *nix pour la classe d'ordinateurs x86. Heureusement pour lui, un certain Linus Torvalds l'a devancé — lui évitant ainsi la peine (une fois de plus) d'écrire effectivement du code. En signe de gratitude éternelle, il a passé beaucoup de temps à expérimenter et promouvoir le système Linux et le projet GNU depuis lors, au grand dam de la plupart de son entourage, qui pense qu'il devrait se concentrer sur la recherche en mathématiques — qui est son gagne-pain. L'interaction entre les programmes s'exécutant réellement, ce qui peut être calculé en théorie et ce dont on peut prouver l'existence, continuent de le fasciner.

Adaptation française de la Gazette Linux

L'adaptation française de ce document a été réalisée dans le cadre du Projet de traduction de la Gazette Linux.

Vous pourrez lire d'autres articles traduits et en apprendre plus sur ce projet en visitant notre site : http://wiki.traduc.org/Gazette_Linux.

Si vous souhaitez apporter votre contribution, n'hésitez pas à nous rejoindre, nous serons heureux de vous accueillir.



[1] C'est-à-dire mettre à l'état « SLEEP ». (N. d. T.)