top(1) プログラムを実験中で、指定されたプログラム名のみを表示する方法を調べてみます。たとえば、次のようにコマンドラインを呼び出すと
$ ssh localhost sleep 15
sshd
プログラム名とインプロセスのみを表示するようにトップ表示をフィルタリングできるようにしたいですsleep
。
top の実行中に「O」(大文字の oh == 大文字と小文字を区別するフィルター) を押してフィルターを追加すると、期待どおりにCOMMAND=sshd
表示されます。 topは、プログラム名で始まるプロセスのみを表示しますsshd
。そのフィルタを削除して(「=」を押す)、新しいフィルタを作成すると、プログラムが起動するCOMMAND=sleep
プロセスが表示されますsleep
。
COMMAND=sshd
ただし、filter1があり、filter2が2つのフィルタを作成すると、実行中のプロセスがあっても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構造体を使用してoro
コマンドを実装していることがわかりました。O
ここで、sel = strcasestr
orsel = strstr
は入力に設定されます(例:)COMMAND=somestring
。あなたは見ることができますGitLabこれはバージョンのコードです。それ以来変わりましたが、非常に似ています。
実装方法または2つの文字列の間で行うのは少し難しいように見えますが、単純な代替案は単に文字列比較を実行する代わりに正規表現を許可するようです。その後、割り当てを変更して2つの文字列を使用して代わりにsel = myfunction
実行する関数を作成できます。regexec()
strstr()
プログラムをダウンロードしてコンパイルしたくない場合は、Cライブラリの前にロードされる小さなシムを作成して、関数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()
。