Filtrar topo (1) exibir por COMMAND = abc OU COMMAND = xyz

2

Estou experimentando o programa top (1) e estou tentando descobrir como exibir apenas os nomes dos programas especificados. Por exemplo, se eu invoco uma linha de comando como

$ ssh localhost sleep 15

Gostaria de filtrar a exibição de top para mostrar apenas os processos cujos nomes de programas são sshd e sleep .

Quando a parte superior está em execução, se eu pressionar 'O' (maiúscula oh == filtro sensível a maiúsculas e minúsculas) e adicionar um filtro COMMAND=sshd , vejo o que espero: top exibe apenas os processos cujos nomes de programa começam com% código%. Se eu excluir esse filtro (pressione '=') e criar um novo filtro sshd , vejo os processos cujos programas começam com COMMAND=sleep .

No entanto, se eu criar dois filtros em que o filtro 1 é sleep e o filtro 2 é COMMAND=sshd , o topo não exibirá nada, mesmo quando houver processos COMMAND=sleep e sshd em execução. Portanto, aparentemente, esse método de criação de filtro produz uma relação sleep : show if AND & & %código%.

Então, como eu crio um filtro (ou conjunto de filtros) que produz o relacionamento OR desejado: mostre se COMMAND=sshd || COMMAND=sleep ?

    
por Jim Fischer 17.08.2018 / 06:51

1 resposta

0

Com o código-fonte aberto, você pode ver o código e ver se pode ser fácil fazer o que quiser. No meu antigo Fedora baseado em rpm, eu poderia facilmente baixar e descompactar a fonte com

$ rpm -qf /usr/bin/top
procps-ng-3.3.10-11.fc24.x86_64
$ dnf download --source procps-ng
$ rpm -i procps-ng-3.3.10-11.fc24.src.rpm 
$ rpmbuild -bp ~/rpmbuild/SPECS/procps-ng.spec --nodeps
$ cd ~/rpmbuild/BUILD/procps-ng-3.3.10/

e o código está em top/top.c . Procurando a palavra filtro , eventualmente, mostra que a função other_selection() está implementando o comando o ou O com uma estrutura C pequena na qual sel = strcasestr ou sel = strstr está sendo definido para entrada como como COMMAND=somestring . Você pode ver o código gitlab desta versão. Ele mudou desde então, mas é semelhante.

Um meio de implementar um ou entre 2 strings parecia um pouco difícil, mas uma alternativa simples parece aceitar uma expressão regular em vez de apenas fazer uma comparação de strings. Você pode então alterar a atribuição para sel = myfunction e escrever uma função que leve 2 strings e faça um regexec() em vez de strstr() .

Se você preferir não baixar e compilar o programa, você pode escrever um pequeno shim para carregar na frente da biblioteca C que substitui a função strstr() por sua própria. No entanto, eu achei que essa função foi usada em outros lugares por top , então eu preferi substituir strcasestr() , que parece ser usado apenas para o comando o . Crie um arquivo shim_strcasestr.c com o seguinte:

/* capture calls to a routine and replace with your code
 * https://unix.stackexchange.com/a/463461/119298
 * gcc -Wall -O2 -fpic -shared -ldl -o shim_strcasestr.so shim_strcasestr.c */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <regex.h>
#define NUMMATCH 1 /* max num matching capture groups in pattern */
char *strcasestr(const char *haystack, const char *needle){
    static char *(*real_strcasestr)(const char *haystack, const char *needle) = NULL;
    regex_t myexpn;
    regmatch_t matches[NUMMATCH] = {0};
    if (!real_strcasestr) {
        real_strcasestr = dlsym(RTLD_NEXT, "strcasestr");
        char *error = dlerror();
        if (error != NULL) {
            fprintf(stderr, "%s\n", error);
            exit(1);
        }
    }
    if(needle[0]!='/') return real_strcasestr(haystack,needle);
    int rc = regcomp(&myexpn, needle+1, REG_EXTENDED);
    if(rc!=0)return NULL;
    rc = regexec(&myexpn, haystack, NUMMATCH, matches, 0);
    regfree(&myexpn);
    if(rc==REG_NOMATCH)return NULL;
    return (char*)haystack;
}

e compile como mostrado no comentário. Você pode, então, executá-lo como LD_PRELOAD=./shim_strcstr.so /usr/bin/top e, quando digitar a chave o , poderá inserir, por exemplo, COMMAND=/sshd|sleep e obter o resultado desejado. Eu adicionei uma verificação para um / inicial na string, então você ainda pode obter a correspondência original de qualquer caso, se você omiti-lo. Obviamente, esse código pode ser otimizado para armazenar em cache o resultado regcomp() .

    
por 19.08.2018 / 11:31

Tags