Forum Astuces.divers [X-Window] top + xrootconsole

Posté par  .
Étiquettes : aucune
0
6
août
2005
Voulant afficher un top sur mon bureau, j'ai naturellement lancé top | xrootconsole. Malheur, on voit des caractères hideux. man top me renseigne, je lance donc top -b | xrootconsole [et des option]. Et là, petit problème : top -b fait défiler des 'top', et donc ça défile dans la console, ce qui est évidemment inutilisable. J'ai donc écrit un (très laid) petit programme en C à glisser entre top et xrootconsole :

#include <stdio.h>

int read_line(FILE *f, char *s, int slength){
int i=0,l;
while((l=fgetc(f))!='\n'){
if(l==EOF){
s[i]='\0';
return 1;
}else{
s[i]=(unsigned char)l;
i++;
}
if(i>=slength-1){
s[i]='\n';
s[i+1]='\0';
while((l=fgetc(f))!='\n' && l!=EOF);
if(l==EOF) return 1;
else break; //returns 0
}
}
s[i]='\n';
s[i+1]='\0';
return 0;
}

int get_proc_count(char *s){
int i=0, j=0;
char tab[20];
while(s[i]!=' ') i++;
while(s[i]==' ') i++;
// while(s[i]!=' ') i++;
//while(s[i]==' ') i++; //décommenter ces lignes si vous utilisez l'option -i avec top
//while(s[i]!=' ') i++;
//while(s[i]==' ') i++;
while(s[i]!=' '){
tab[j]=s[i];
j++;
i++;
}
tab[j]='\0';
return atoi(tab);
}

int min(int a, int b){
if(a<=b) return a;
else return b;
}

int main(int argc, char *argv[]){
int lines_total=0, i, pcount;
char buff[256];
if(argc<2){
printf("usage : toptop <line number>\n");
return 1;
}
lines_total=atoi(argv[1]);
while(1){
if(read_line(stdin, buff, 255)){ //read first line
fclose(stdout);
return 0;
}else printf("%s", buff);
if(read_line(stdin, buff, 255)){ //read second line
fclose(stdout);
return 0;
}else printf("%s", buff);
pcount = get_proc_count(buff); //second line contains (active) tasks number
for(i=0;i<min(5+pcount,lines_total-2);i++){ //print all lines, depending on the tasks number
if(read_line(stdin, buff, 255)){
fclose(stdout);
return 0;
}else printf("%s", buff);
}
for(i=0;i<lines_total-8-pcount;i++) printf("\n"); //fill with empty lines
fflush(stdout);
while(strcmp(buff, "\n")){ //get lines until the end of the top output
if(read_line(stdin, buff, 255)){
fclose(stdout);
return 0;
}
}
if(read_line(stdin, buff, 255)){
fclose(stdout);
return 0;
}
}
return 0;
}

Je peux donc faire un petit top -b | monprog <nombre_de_lignes> | xrootconsole -geometry <nb_colonnes>x+0+0 (il faut peut-être remplacer <nombre_de_lignes> par <nombre_de_lignes+1>, car ce programme est mal écrit), et ça marche : le top ne bouge pas, et s'il est trop long il est tronqué. Voilà, si ça intéresse quelqu'un, j'ai écrit un programme dans le même genre (couplé à un script) pour netstat, y'a qu'à demander. Bon pour df évidemment, y'a pas de problème.
Bonnes vacances à tous.
  • # Il manque des ...

    Posté par  . Évalué à 2.

    ... &nbsp;

    Pour réparer ça:

    cat le-prog-copier-coller.c | indent > le-prog-bien-indenté.c


    Sinon il suffit de désactiver le HTML avant de poster le message ou de préparer le source à coup de sed 's/ /\&nbsp;/g'. C'est plus jolie ensuite :)
  • # Une version Perl

    Posté par  . Évalué à 2.

    ... avec l'appel à top intégré :

    #!/usr/bin/perl -w
    use strict;

    my $nb = shift @ARGV or die "Utilisation : $0 <nombre de lignes>\n";

    # On ouvre un pipe depuis la commande top -b en entrée
    open TOP, "top -b|" or die "Impossible de lancer la commande top -b\n";
    # Deux affichages consécutifs de top -b sont séparées par deux lignes vides
    # Donc en définissant le séparateur d'enregistrements ainsi :

    $/ = "\n\n\n";
    # on obtiendra une sortie complète à chaque accès au file handle.
    while (<TOP>) {
        # À ce stade-là, on sépare l'enregistrement courant en lignes
        my @ligne = split /\n/;
        # et on affiche les $nb premières lignes (ou une ligne vide pour les lignes
        # éventuellement non définies) en remettant une fin de ligne.

        print map({($_ || '')."\n"} @ligne[0 .. $nb - 1]);
    }
    close TOP;



    Ou en uniligne :
    top -b | perl -ne 'BEGIN { $/="\n\n\n" } print map({($_ || "")."\n"} (split /\n/)[0..39])' | xrootconsole
    où il faut remplacer 39 par le nombre de lignes - 1.

    Toujours pas tenté par Perl ?
    Cela dit, on doit pouvoir faire à peu près aussi court en Python ou en Ruby...

    « Le fascisme c’est la gangrène, à Santiago comme à Paris. » — Renaud, Hexagone

    • [^] # Uniligne simplifié

      Posté par  . Évalué à 2.

      En fait, on peut simplifier la version uniligne :

      top -b | perl -ne 'BEGIN { $/="\n\n\n" } print map "$_\n", (split /\n/)[0..39]' | xrootconsole

      vu que sans les warnings (-w) Perl ne va pas se formaliser de détails comme imprimer une variable indéfinie puisqu'initialisée avec un élément de tableau inexistant.
      (Inutile de dire par contre, que si l'on fait des programmes conséquents sans les warnings, on peut chercher les bugs longtemps...)

      « Le fascisme c’est la gangrène, à Santiago comme à Paris. » — Renaud, Hexagone

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.