<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD>  <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.7">  <META Name="keywords" Content="Linux, francais, franais, france,        GNU, FSF, Debian, Redhat, Slackware, Mandrake, kheops, document,        documentation, logiciel, libre, informatique, free, software, open,        source, sourceware, freeware, soleil, support, assistance, hot line">  <META Name="description" Content="Ce document regroupe         l'adaptation d'articles parus dans la Linux-Gazette. Merci  Nat         Makarvitch pour ses relectures et Jol Bernier pour la mise en page         HTML.">  <TITLE>Morceaux choisis de la Linux Gazette N33: CHAOS deuxi&egrave;me partie: Pr&eacute;parer les outils syst&egrave;me</TITLE>  <LINK HREF="lg-33-3.html" REL=next>  <LINK HREF="lg-33-1.html" REL=previous>  <LINK HREF="lg-33.html#toc2" REL=contents>  <BODY bgcolor="#ffffff" text="#000000" link="#0000ff" alink="#ff0000" vlink="#ff0000"> </HEAD>  <CENTER>  <BLOCKQUOTE>  <TABLE width="600">  <TR rowspan=1 align="left">  <TD colspan=1 align="left"> <!--============= Debut du chapitre ==================--> <HR size=2 noshade>  <A HREF="lg-33-3.html">Page suivante</A> <A HREF="lg-33-1.html">Page prcdente</A> <A HREF="lg-33.html#toc2">Table des matires</A> <HR size=2 noshade> <H2><A NAME="s2">2. CHAOS deuxi&egrave;me partie: Pr&eacute;parer les outils syst&egrave;me</A></H2>  <P>Par  <A HREF="mailto:P29131@gegpo6.geg.mot.com">Alex Vrenios</A><P> <H2><A NAME="ss2.1">2.1 Introduction</A> </H2>  <P>Mon premier article, "CHAOS: CHeap Array of Obsolete Systems"  (voir Linux Gazette 30, Juillet 1998),  d&eacute;crivait l'encha&icirc;nement d'impr&eacute;vus qui m'a conduit &agrave; construire un petit r&eacute;seau de PCs obsol&egrave;tes tournant sous Linux (Red Hat). Suite &agrave; cet article, de nombreux lecteurs m'ont contact&eacute; pour me demander la tournure que cela prenait et si il y aurait un autre article sur ce th&egrave;me: le voici ! <P> <P>Quelques PCs, un syst&egrave;me d'exploitation et un peu de mat&eacute;riel r&eacute;seau constituent la base indispensable &agrave; la r&eacute;alisation du type de syst&egrave;mes que je d&eacute;sire b&acirc;tir, mais cette base n'est pas suffisante pour autant. Un peu d'administration, quelques scripts de commandes et autres petits utilitaires vont permettre d'en faire ce que je veux obtenir: un syst&egrave;me distribu&eacute;. <P> <P>Les algorithmes distribu&eacute;s ne sont souvent que plusieurs copies identiques du m&ecirc;me programme s'ex&eacute;cutant sur diff&eacute;rentes machines du m&ecirc;me r&eacute;seau. Je peux bien s&ucirc;r &eacute;crire et d&eacute;bugger un exemplaire d'un programme sur mon <EM>gros</EM> 486, nomm&eacute; Omission, mais ce n'est que la premi&egrave;re &eacute;tape. Debugger le produit final, celui qui s'ex&eacute;cute sur sept machines simultan&eacute;ment, demande de pouvoir d&eacute;marrer &agrave; distance un processus sur chacune des machines, regarder comment il s'ex&eacute;cute, puis le tuer si n&eacute;cessaire, en centralisant les fichiers de trace en un endroit unique pour me permettre de comprendre ce qui n'a pas fonctionn&eacute;. <P> <P>Cet article d&eacute;crit ce que j'ai ajout&eacute; &agrave; mon syst&egrave;me pour permettre tout cela. <P> <H2><A NAME="ss2.2">2.2 Administration syst&egrave;me</A> </H2>  <P>J'ai travaill&eacute; avec de nombreux r&eacute;seaux Unix par le pass&eacute;. Je n'ai jamais envisag&eacute; d'utiliser la "commande en ligne &agrave; distance", rsh, pour me connecter &agrave; une autre machine du r&eacute;seau et acc&eacute;der &agrave; ses donn&eacute;es locales. Jusqu'&agrave; ce que je d&eacute;cide de l'utiliser sur mon propre r&eacute;seau. <P> <P>Depuis Omission, je vois trois fa&ccedil;ons de me connecter &agrave; l'un des six autres 386. La premi&egrave;re est d'utiliser telnet, qui demande un login et un mot de passe. La deuxi&egrave;me est d'utiliser rlogin, qui me demande un nom d'utilisateur, mais pas de mot de passe, pour peu que les syst&egrave;mes de fichiers soient convenablement install&eacute;s. La troisi&egrave;me, rsh, me laisse changer de machine sans m&ecirc;me me demander de nom d'utilisateur, si tant est que l'on ait tout configur&eacute; comme il faut. D'apr&egrave;s moi, tout configurer comme il faut r&eacute;l&egrave;ve cependant de la magie noire. <P> <P>Je savais que mon r&eacute;pertoire presonnel (home), /home/alex, avait besoin d'un fichier .rhosts contenant mon nom d'utilisateur: une unique ligne "alex". Je savais aussi que le fichier /etc/hosts.equiv jouait un r&ocirc;le important, mais je ne savais pas exactement lequel. J'ai donc commenc&eacute; &agrave; me documenter et &agrave; me poser beaucoup de questions. La plupart des articles sur le sujet s'int&eacute;ressaient plus &agrave; "comment emp&ecirc;cher les autres de rentrer", que "comment les acueillir". <P> <P>Je ne suis pas du genre &agrave; renier l'utilisation de m&eacute;thodes que je qualifierais de "force brute" pour r&eacute;soudre certains probl&egrave;mes. Je suis pr&ecirc;t &agrave; parier qu'un administrateur syst&egrave;me comp&eacute;tent qui lira cet article pourra &ecirc;tre atterr&eacute; par ma m&eacute;thode, mais elle fonctionne, et je m'en suis content&eacute;. <P> <P>Mon nom de domaine, comme les lecteurs du premier article s'en souviennent peut-&ecirc;tre, est "chaos.org" et mes sept 386 portent les noms des sept p&eacute;ch&ecirc;s capitaux. L'utilisateur alex a un r&eacute;pertoire personnel sur Omission, qui est mont&eacute; par NFS sur chacune des sept autres machines. Les fichiers /home/alex/.rhosts et /etc/hosts.equiv ont exactement le m&ecirc;me contenu, &agrave; savoir: <P> <BLOCKQUOTE><CODE> <PRE> omission.chaos.org alex greed.chaos.org alex lust.chaos.org alex anger.chaos.org alex pride.chaos.org alex gluttony.chaos.org alex envy.chaos.org alex sloth.chaos.org alex </PRE> </CODE></BLOCKQUOTE> <P> <P>Je ne suis plus tr&egrave;s s&ucirc;r de l'endroit o&ugrave; j'ai trouv&eacute; le mod&egrave;le de cette configuration, mais &ccedil;a fonctionne, ce qui me suffit pour le moment. <P> <P>Je voulais aussi assurer un minimum de synchronisation entre les horloges des diff&eacute;rents syst&egrave;mes. J'ai donc ajout&eacute; une commande lors du d&eacute;marrage de chaque machine qui r&egrave;gle son horloge sur celle d'Omission. Voici ce qu'on trouve dans le fichier rc.local de chacun des sept 386: <P> <BLOCKQUOTE><CODE> <PRE> # reset date and time from server date `rsh omission "date +%m%d%H%M"` </PRE> </CODE></BLOCKQUOTE> <P> <P>Je d&eacute;marre toujours Omission en premier et attend la fin de son initialisation avant de d&eacute;marrer les autres, car il partage le r&eacute;pertoire /home que doivent monter les autres machines. La pr&eacute;cision de la synchronisation des horloges est inf&eacute;rieure &agrave; la minute. <P> <H2><A NAME="ss2.3">2.3 Syst&egrave;me de fichiers distribu&eacute;</A> </H2>  <P>Il n'existe qu'un exemplaire de /home/alex/.rhosts, mais chaque syst&egrave;me dispose de sa propre copie de /etc/hosts.equiv. Maintenir huit copies identiques de quelque chose n'est jamais plaisant, surtout lorsqu'on proc&egrave;de &agrave; de subtils changements suppos&eacute;s r&eacute;soudre votre probl&egrave;me si toutes les copies sont coh&eacute;rentes. <P> <P>Une premi&egrave;re solution est de copier le fichier en question sur une disquette pour le charger sur chacune des machines, mais cela demande trop d'efforts. Les plus sophistiqu&eacute;s pourront cr&eacute;er une partition sp&eacute;ciale pour ce type de fichiers sur la machine principale et la monter depuis chacune des autres machines. Comme je suis &agrave; la fois l'administrateur syst&egrave;me et la communaut&eacute; d'utilisateur &agrave; moi tout seul, j'en ai profit&eacute; pour entrem&ecirc;ler les deux. <P> <P>J'ai cr&eacute;&eacute; un r&eacute;pertoire /home/alex/root, appartenant &agrave; root, et copi&eacute; tous les fichiers de configuration que je voulais partager dans ce r&eacute;pertoire. Comme /home/alex est mont&eacute; par toutes les machines, je peux ais&eacute;ment modifier ces fichiers en une seule fois. J'ai mis dans ce r&eacute;pertoire /etc/hosts, rc.local et tous les scripts que l'administrateur est susceptible d'utiliser sur l'une ou l'autre des machines. <P> <H2><A NAME="ss2.4">2.4 Utilitaires et scripts d'administration</A> </H2>  <P>Je peux avoir besoin de r&eacute;gler l'horloge manuellement, j'ai donc repris la commande vue plus haut dans un script "settime": <P> <BLOCKQUOTE><CODE> <PRE> #!/bin/csh -f # #   settime - synchronise l'horloge avec celle d'omission # date `rsh omission "date +%m%d%H%M"` </PRE> </CODE></BLOCKQUOTE> <P> <P>Je peux avoir besoin de suivre l'ex&eacute;cution de tests assez long, et comme je suis craintif, je peux vouloir visualiser les performances globales du syst&egrave;me. Voici mon script "ruptime" : <P> <BLOCKQUOTE><CODE> <PRE> #!/bin/csh -f # #   ruptime - affiche les performances du syst&egrave;me # cat /etc/hosts \  | grep -v localhost \  | awk '{ print $3": ";system("rsh "$3" uptime") }' </PRE> </CODE></BLOCKQUOTE> <P> <P>Il affiche la charge de chacune de mes machines. Je l'utilise comme un indicateur global de performances. Le mot charge d&eacute;signe le nombre de processus dans la file "pr&ecirc;te", en attente du processeur. Le processeur est en g&eacute;n&eacute;ral occup&eacute; par l'ex&eacute;cution de la t&acirc;che active. Les trois nombres qu'affiche uptime, sont les charges moyennes sur 1, 5 et 15 minutes (voir la page du manuel pour plus d'informations: man uptime). Si je d&eacute;couvre ce qui peut &ecirc;tre un probl&egrave;me, par exemple un triplet de z&eacute;ros, je peux lancer d'autres commandes pour obtenir plus d'informations. <P> <P>La commande ps affiche l'&eacute;tat de tous les processus du syst&egrave;me. L'utilisation de grep permet ensuite de limiter l'affichage pour n'obtenir que ceux que je d&eacute;sire voir appara&icirc;tre. Voici donc le script rps: <P> <BLOCKQUOTE><CODE> <PRE> #!/bin/csh -f # #   rps - remote process status # ps -aux | grep alex \  | grep -v rps \  | grep -v aux \  | sed -e "s/alex\ \ \ \ \ /`hostname -s`/" \  | grep -v sed \  | grep -v hostname \  | grep -v grep </PRE> </CODE></BLOCKQUOTE> <P> <P>Ci-dessus, la commande sed permet de remplacer mon nom d'utilisateur par le nom de la machine qui ex&eacute;cute le processus. J'utilise alors ce script pour conna&icirc;tre l'&eacute;tat des processus d'une machine donn&eacute;e: <P> <BLOCKQUOTE><CODE> <PRE> omission:/home/alex&gt; rsh pride rps pride  218  0.4  7.0  1156   820   1 S   13:34   0:02 /bin/login -- alex pride  240  0.7  6.6  1296   776   1 S   13:37   0:01 -csh pride  309  0.3  1.8   856   212   1 S   13:41   0:00 ser pride  341  0.0  4.4  1188   524  ?  R   13:41   0:00 /bin/sh /home/alex/bin </PRE> </CODE></BLOCKQUOTE> <P> <P>Les lecteurs attentifs auront remarqu&eacute; que le script ruptime affiche la charge de toutes les machines du r&eacute;seau, alors que rps ne s'applique qu'&agrave; une seule machine. Une seconde version de rps est donc utilis&eacute;e: le script rpsm, qui fait appel &agrave; rstart et psm. <P> <BLOCKQUOTE><CODE> <PRE> #!/bin/csh -f # #   rpsm - remote process status for my userid # rstart psm </PRE> </CODE></BLOCKQUOTE> <P> <P>Le program rstart.c accepte en argument le nom d'un ex&eacute;cutable: <P> <BLOCKQUOTE><CODE> <PRE> #include &lt;stdio.h&gt; #include &lt;chaos.h&gt; /* une liste de toutes les machines de chaos.org */ main(argc, argv) char *argv[]; int argc; /* **   rstart.c - lance le processus nomm&eacute; argv[1] sur chacune des machines */ {    int i, j, pids[NUM];    char command[64];    /*    **   demande au moins deux arguments    */    if(argc &lt; 2) {       printf("\n\tUsage: %s &lt;process&gt; [&lt;parameters&gt;]\n\n", argv[0]);       exit(-1);    }    close(0); /* &eacute;vite des probl&egrave;mes avec stdin si on tourne en t&acirc;che de fond */    /*    **   initialise le nom du processus distant    */    strcpy(command, argv[1]);    if(command[0] != '/') /* ajoute le chemin si n&eacute;cessaire */       sprintf(command, "%s%s", Bin, argv[1]);    /*    **   ajoute les autres arguments    */    for(i=2; i&lt;argc; i++) {       strcat(command, " "); /* ajoute un espace */       strcat(command, argv[i]); /* ajoute un param&egrave;tre */    }    /*    **   lance les processus distants    */    for(i=0; i&lt;NUM; i++) {       if(i) /* petite pause entre chaque lancement */          sleep(1);       if((pids[i] = fork()) == 0) {          if(execl("/usr/bin/rsh", "rsh", Hosts[i], command, NULL) == -1) {             perror("execl()");             exit(-1);          }       }    }    /*    **   attend la fin de chacun des processus    */    for(i=1; i&lt;NUM; i++)       waitpid(pids[i]);    return(0); } </PRE> </CODE></BLOCKQUOTE> <P> <P>Le script rpsm ci-dessus utilise rstart, qui utilise psm, que voici: <P> <BLOCKQUOTE><CODE> <PRE> #include &lt;string.h&gt; #include &lt;stdio.h&gt; main() /* **   psm.c - affiche l'&eacute;tat de mes processus */ {    FILE *fp;    int len, pid1, pid2;    char host[32], *p;    char line[128];    /* nom de notre hote ? */    gethostname(host, sizeof(host));    if((p = strchr(host, '.')) != NULL)       *p = '\0'; /* coupe nom de domaine */    len = strlen(host);    /* le pid de notre proc */    pid1 = getpid();    /* liste de l'&eacute;tat de tous les processus */    fp = popen("ps -aux", "r");    while(fgets(line, sizeof(line), fp) != NULL) {       if(strstr(line, "alex ") == NULL)          continue; /* pas &agrave; nous */       if(strstr(line, "psm") != NULL)          continue; /* ne pas s'auto-afficher */       sscanf(line, "%*s %d", &amp;pid2);       if(pid2 &gt;= pid1)          continue; /* oublie les plus grands */       /* remplace utilisateur par hote */       strncpy(line, host, len);       printf("%s", line);    }    return(0); } </PRE> </CODE></BLOCKQUOTE> <P> <P>Voici un exemple: <P> <BLOCKQUOTE><CODE> <PRE> &gt; rpsm pride   218  0.0  7.0  1156   820   1 S   13:34   0:02 /bin/login -- alex  pride   240  0.0  6.6  1296   776   1 S   13:37   0:01 -csh  pride   309  0.0  1.8   856   212   1 S   13:41   0:00 ser  pride   487 38.3  5.4  1240   636  ?  S   14:17   0:01 csh -c /home/alex/bin greed   222 35.8  7.3  1240   636  ?  S   14:17   0:01 csh -c /home/alex/bin    .    .    . sloth   201 36.5  7.1  1240   636  ?  S   14:17   0:01 csh -c /home/alex/bin </PRE> </CODE></BLOCKQUOTE> <P> <P>Le principe du programme rstart peut &ecirc;tre &eacute;tendu pour obtenir bien plus que l'&eacute;tat des processus. J'ai cr&eacute;&eacute; des paires de programmes et de scripts pour obtenir le fichier trace et le fichier log d'une machine. Je peux aussi tuer un processus distant en d'apr&egrave;s son nom en appelant le programme suivant (k.c) avec rstart: <P> <BLOCKQUOTE><CODE> <PRE> #include &lt;string.h&gt; #include &lt;stdio.h&gt; main(argc, argv) int argc; char *argv[]; /* **   k.c - tuer le processus nomm&eacute; xxx */ {    FILE *fp;    int pid1, pid2;    char line[128];    char shell[32];    char host[32];    char proc[16];    if(argc &lt; 2 || argc &gt; 3) {       printf("\tUsage: k &lt;process_name&gt; [noconf]\n\n");       exit(-1);    }    /* obtienir le nom du processus */    sprintf(proc, "%s ", argv[1]); /* ajoute espace */    sprintf(shell, "-c k %s", proc); /* notre parent */    pid1 = getpid();    /* hote = ? utile pour affichage */    gethostname(host, sizeof(host));    /* liste de l'&eacute;tat des processus */    fp = popen("ps -aux", "r");    while(fgets(line, sizeof(line), fp) != NULL) {       if(strstr(line, "alex ") == NULL)          continue; /* pas nous */       if(strstr(line, shell) != NULL)          continue; /* &eacute;vite shell */       if(strstr(line, proc) == NULL)          continue; /* doit correspondre */       sscanf(line, "%*s %d", &amp;pid2);       if(pid2 &gt;= pid1)          continue; /* &eacute;vite les plus grands */       /* tue le processus */       system(line);       sprintf(line, "kill -9 %d", pid2);       if(argc != 3)          printf("%s: %s\n", host, line);    }    return(0); } </PRE> </CODE></BLOCKQUOTE> <P> <P> <P>Tous les programmes ci-dessus ont &eacute;t&eacute; copi&eacute;s et coll&eacute;s dans cet article &agrave; partir du code source "test&eacute; et approuv&eacute;", mais j'ai supprim&eacute; des lignes blanches et modifi&eacute; quelque peu la pr&eacute;sentation pour les rendre plus lisibles. Pardonnez-moi par avance des &eacute;ventuelles difficult&eacute;s que vous pourrez rencontrer en les utilisant. Sachez d'autre part que je ne suis responsable en aucune sorte de l'utilisation que vous en ferez, agissez-donc &agrave; vos risques et p&eacute;rils. <P> <H2><A NAME="ss2.5">2.5 Conclusion</A> </H2>  <P>Je crois que je suis maintenant pr&ecirc;t &agrave; d&eacute;velopper des logiciels conform&eacute;ment &agrave; mon id&eacute;e de d&eacute;part. J'esp&egrave;re que quelques-unes de mes solutions pourront vous aider, au cas ou vous d&eacute;cideriez d'essayer tout ceci par vous-m&ecirc;me. <P> <P>La prochaine &eacute;tape sera de d&eacute;velopper un programme de contr&ocirc;le centralis&eacute; des t&acirc;ches, s'ex&eacute;cutant sur Omission, qui pourra afficher en temps-r&eacute;el l'&eacute;tat et le comportement du <EM>syst&egrave;me de processus distribu&eacute;s</EM> s'ex&eacute;cutant sur les autres machines. Je voudrais &ecirc;tre capable de diriger le syst&egrave;me en envoyant des requ&ecirc;tes &agrave; l'un des processus sur l'une quelconque des machines, avant d'observer comment les diff&eacute;rents processus interagissent pour formuler leur r&eacute;ponse. Chaque processus distant devra interagir avec un "agent", un processus local, qui s'ex&eacute;cutera en parall&egrave;le. Chaque agent enverra en retour des messages au programme de contr&ocirc;le central, lui indiquant l'&eacute;tat courant de cette partie du syst&egrave;me. Lequel programme pourra combiner les diff&eacute;rentes r&eacute;ponses pour pr&eacute;senter une synth&egrave;se de l'&eacute;tat du syst&egrave;me distribu&eacute;. Si le sujet vous int&eacute;resse, retez &agrave; l'&eacute;coute. <P> <P>Ce projet m'a beaucoup appris. Je suis fier de ce que j'ai b&acirc;ti et j'esp&egrave;re que ces outils tr&egrave;s simples encouragerons certains d'entre vous &agrave; tenter l'exp&eacute;rience, avec peut-&ecirc;tre trois ou quatre machines, ou m&ecirc;me plus que les huit que j'ai r&eacute;unies. Les r&eacute;seaux "&agrave; la maison" sont &agrave; la mode, en ce moment, et d&eacute;velopper des logiciels qui tirent parti des avantages d'un r&eacute;seau ne peut qu'en d&eacute;couler. Essayez-donc si vous l'osez et pr&eacute;parez-vous &agrave; entrer dans le futur. <P> <HR> <P>Traduction fran&ccedil;aise Nicolas Chauvat <A HREF="mailto:nico@caesium.fr">&lt;nico@caesium.fr&gt;</A><HR size=2 noshade> <A HREF="lg-33-3.html">Page suivante</A> <A HREF="lg-33-1.html">Page prcdente</A> <A HREF="lg-33.html#toc2">Table des matires</A> <HR size=2 noshade> <!--============== Fin du chapitre ===================--> </BLOCKQUOTE> </TR></TD></TABLE> </CENTER> </BODY> </HTML> 
