%20%ED%91%9C%EC%8B%9C%20%ED%95%84%ED%84%B0%EB%A7%81.png)
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 && .sshd
sleep
AND
COMMAND=sshd
COMMAND=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 구조체를 사용하여 o
or 명령을 구현하고 있는 것으로 나타났습니다 . O
여기서 sel = strcasestr
or sel = strstr
는 입력으로 설정됩니다(예: ) COMMAND=somestring
. 너는 볼 수있어GitLab이 버전의 코드입니다. 그 이후로 바뀌었지만 매우 유사합니다.
구현 방법또는두 문자열 사이에서 수행하는 것은 약간 어려운 것처럼 보이지만 간단한 대안은 단순히 문자열 비교를 수행하는 대신 정규식을 허용하는 것 같습니다. 그런 다음 할당을 변경 하고 2개의 문자열을 사용하여 대신 을 sel = myfunction
수행하는 함수를 작성할 수 있습니다 .regexec()
strstr()
프로그램을 다운로드하고 컴파일하고 싶지 않다면 C 라이브러리 앞에 로드되는 작은 shim을 작성하여 strstr()
함수를 자신의 함수로 재정의할 수 있습니다. 하지만 이 기능은 다른 곳에서도 사용되는 것을 발견했기 때문에 명령 에만 사용되는 것으로 보이는 이 top
기능을 재정의하는 것을 선호합니다 . 다음 내용으로 파일을 만듭니다 .strcasestr()
o
shim_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()
.