COMMAND=abc 또는 COMMAND=xyz로 상단(1) 표시 필터링

COMMAND=abc 또는 COMMAND=xyz로 상단(1) 표시 필터링

top(1) 프로그램을 실험 중이며 지정된 프로그램 이름만 표시하는 방법을 알아보려고 합니다. 예를 들어, 다음과 같이 명령줄을 호출하면

$ ssh localhost sleep 15

sshd프로그램 이름이 및 인 프로세스 만 표시하도록 top 표시를 필터링할 수 있기를 원합니다 sleep.

top이 실행되는 동안 "O"(대문자 oh == 대소문자 구분 필터)를 누르고 필터를 추가하면 COMMAND=sshd예상한 대로 표시됩니다. top은 프로그램 이름이 로 시작하는 프로세스만 표시합니다 sshd. 해당 필터를 삭제하고("=" 누르기) 새 필터를 생성하면 COMMAND=sleep프로그램에서 시작하는 프로세스가 표시됩니다 sleep.

COMMAND=sshd그러나 filter1이 이고 filter2가 인 두 개의 필터를 생성하면 실행 중인 프로세스 가 COMMAND=sleep있어도 상단에는 아무 것도 표시되지 않습니다 . 분명히 필터를 생성하는 이 방법은 관계를 생성합니다: show if && .sshdsleepANDCOMMAND=sshdCOMMAND=sleep

그렇다면 원하는 OR 관계를 생성하는 필터(또는 필터 세트)를 어떻게 생성합니까? show if COMMAND=sshd||COMMAND=sleep

답변1

오픈소스를 사용하면 코드를 보고 원하는 작업을 쉽게 수행할 수 있는지 확인할 수 있습니다. 이전 RPM 기반 Fedora에서는 소스 코드를 쉽게 다운로드하고 압축을 풀 수 있었습니다.

$ 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/

코드는 에서 top/top.c단어를 찾습니다 .필터other_selection()궁극적으로 함수는 작은 C 구조체를 사용하여 oor 명령을 구현하고 있는 것으로 나타났습니다 . O여기서 sel = strcasestror sel = strstr는 입력으로 설정됩니다(예: ) COMMAND=somestring. 너는 볼 수있어GitLab이 버전의 코드입니다. 그 이후로 바뀌었지만 매우 유사합니다.

구현 방법또는두 문자열 사이에서 수행하는 것은 약간 어려운 것처럼 보이지만 간단한 대안은 단순히 문자열 비교를 수행하는 대신 정규식을 허용하는 것 같습니다. 그런 다음 할당을 변경 하고 2개의 문자열을 사용하여 대신 을 sel = myfunction수행하는 함수를 작성할 수 있습니다 .regexec()strstr()

프로그램을 다운로드하고 컴파일하고 싶지 않다면 C 라이브러리 앞에 로드되는 작은 shim을 작성하여 strstr()함수를 자신의 함수로 재정의할 수 있습니다. 하지만 이 기능은 다른 곳에서도 사용되는 것을 발견했기 때문에 명령 에만 사용되는 것으로 보이는 이 top기능을 재정의하는 것을 선호합니다 . 다음 내용으로 파일을 만듭니다 .strcasestr()oshim_strcasestr.c

/* 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;
}

주석에 표시된 대로 컴파일됩니다. 그런 다음 실행 LD_PRELOAD=./shim_strcstr.so /usr/bin/top하고 해당 키를 입력하면 o예를 들어 COMMAND=/sshd|sleep원하는 결과를 얻을 수 있습니다. /문자열의 이니셜 검사를 추가했으므로 이를 생략해도 원래의 임의 대소문자 일치를 얻을 수 있습니다. 분명히 이 코드는 결과를 캐시하도록 최적화될 수 있습니다 regcomp().

관련 정보