COMMAND=abc または COMMAND=xyz でトップ (1) 表示をフィルタリング

COMMAND=abc または COMMAND=xyz でトップ (1) 表示をフィルタリング

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 && 。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構造体を使用してoroコマンドを実装していることがわかりました。Oここで、sel = strcasestrorsel = strstrは入力に設定されます(例:)COMMAND=somestring。あなたは見ることができますGitLabこれはバージョンのコードです。それ以来変わりましたが、非常に似ています。

実装方法または2つの文字列の間で行うのは少し難しいように見えますが、単純な代替案は単に文字列比較を実行する代わりに正規表現を許可するようです。その後、割り当てを変更して2つの文字列を使用して代わりにsel = myfunction実行する関数を作成できます。regexec()strstr()

プログラムをダウンロードしてコンパイルしたくない場合は、Cライブラリの前にロードされる小さなシムを作成して、関数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()

関連情報