Как отслеживать вновь созданные процессы в Linux?

Всего восемь? Если верить старым вопросам SE, то в 2010 году было 31 CD, а в 2012 - 52...

Если у вас есть хоть сколько-нибудь вменяемое подключение к Интернету, вам нужен только первый, или только netinst образ. Так было на протяжении многих лет, и я не помню, чтобы я когда-либо загружал изображения 2-N. Они там в основном для того, чтобы вы могли установить систему даже на компьютер в глуши леса без подключения к Интернету.

В руководстве по установке для jessie говорится, что:

Много усилий было потрачено на то, чтобы наиболее используемые файлы были на первых CD и DVD, так что базовая установка рабочего стола может быть выполнена только с первого DVD или - в ограниченной степени - даже только с первого CD.

Поскольку компакт-диски имеют довольно ограниченную емкость по сегодняшним стандартам, не все графические среды рабочего стола можно установить только с первого компакт-диска; для некоторых сред рабочего стола установка с компакт-диска требует либо подключения к сети во время установки для загрузки оставшихся файлов, либо дополнительных компакт-дисков.

Так что даже если вам нужно что-то, чего нет на первом диске, программа установки будет рада загрузить это для вас.

31
16.04.2018, 15:39
6 ответов

Если в ядре включены kprobes, вы можете использовать execsnoop из perf-tools :

В первом терминале:

% while true; do uptime; sleep 1; done

В другом терминале:

% git clone https://github.com/brendangregg/perf-tools.git
% cd perf-tools
% sudo ./execsnoop
Tracing exec()s. Ctrl-C to end.
Instrumenting sys_execve
   PID   PPID ARGS
 83939  83937 cat -v trace_pipe
 83938  83934 gawk -v o=1 -v opt_name=0 -v name= -v opt_duration=0 [...]
 83940  76640 uptime
 83941  76640 sleep 1
 83942  76640 uptime
 83943  76640 sleep 1
 83944  76640 uptime
 83945  76640 sleep 1
^C
Ending tracing...
36
27.01.2020, 19:38

CONFIG_PROC_EVENTS=y

Пример сеанса:

$ su
#./proc_events.out &
set mcast listen ok
# sleep 2 & sleep 1 &
fork: parent tid=48 pid=48 -> child tid=56 pid=56
fork: parent tid=48 pid=48 -> child tid=57 pid=57
exec: tid=57 pid=57
exec: tid=56 pid=56
exit: tid=57 pid=57 exit_code=0
exit: tid=56 pid=56 exit_code=0

CONFIG_PROC_EVENTSпредоставляет доступ к событиям пользователю через сокет netlink .

proc _events.c

#define _XOPEN_SOURCE 700
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/connector.h>
#include <linux/cn_proc.h>
#include <signal.h>
#include <errno.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

static volatile bool need_exit = false;

static int nl_connect()
{
    int rc;
    int nl_sock;
    struct sockaddr_nl sa_nl;

    nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
    if (nl_sock == -1) {
        perror("socket");
        return -1;
    }
    sa_nl.nl_family = AF_NETLINK;
    sa_nl.nl_groups = CN_IDX_PROC;
    sa_nl.nl_pid = getpid();
    rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
    if (rc == -1) {
        perror("bind");
        close(nl_sock);
        return -1;
    }
    return nl_sock;
}

static int set_proc_ev_listen(int nl_sock, bool enable)
{
    int rc;
    struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
        struct nlmsghdr nl_hdr;
        struct __attribute__ ((__packed__)) {
            struct cn_msg cn_msg;
            enum proc_cn_mcast_op cn_mcast;
        };
    } nlcn_msg;

    memset(&nlcn_msg, 0, sizeof(nlcn_msg));
    nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg);
    nlcn_msg.nl_hdr.nlmsg_pid = getpid();
    nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE;

    nlcn_msg.cn_msg.id.idx = CN_IDX_PROC;
    nlcn_msg.cn_msg.id.val = CN_VAL_PROC;
    nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);

    nlcn_msg.cn_mcast = enable ? PROC_CN_MCAST_LISTEN : PROC_CN_MCAST_IGNORE;

    rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
    if (rc == -1) {
        perror("netlink send");
        return -1;
    }

    return 0;
}

static int handle_proc_ev(int nl_sock)
{
    int rc;
    struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
        struct nlmsghdr nl_hdr;
        struct __attribute__ ((__packed__)) {
            struct cn_msg cn_msg;
            struct proc_event proc_ev;
        };
    } nlcn_msg;
    while (!need_exit) {
        rc = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
        if (rc == 0) {
            /* shutdown? */
            return 0;
        } else if (rc == -1) {
            if (errno == EINTR) continue;
            perror("netlink recv");
            return -1;
        }
        switch (nlcn_msg.proc_ev.what) {
            case PROC_EVENT_NONE:
                printf("set mcast listen ok\n");
                break;
            case PROC_EVENT_FORK:
                printf("fork: parent tid=%d pid=%d -> child tid=%d pid=%d\n",
                        nlcn_msg.proc_ev.event_data.fork.parent_pid,
                        nlcn_msg.proc_ev.event_data.fork.parent_tgid,
                        nlcn_msg.proc_ev.event_data.fork.child_pid,
                        nlcn_msg.proc_ev.event_data.fork.child_tgid);
                break;
            case PROC_EVENT_EXEC:
                printf("exec: tid=%d pid=%d\n",
                        nlcn_msg.proc_ev.event_data.exec.process_pid,
                        nlcn_msg.proc_ev.event_data.exec.process_tgid);
                break;
            case PROC_EVENT_UID:
                printf("uid change: tid=%d pid=%d from %d to %d\n",
                        nlcn_msg.proc_ev.event_data.id.process_pid,
                        nlcn_msg.proc_ev.event_data.id.process_tgid,
                        nlcn_msg.proc_ev.event_data.id.r.ruid,
                        nlcn_msg.proc_ev.event_data.id.e.euid);
                break;
            case PROC_EVENT_GID:
                printf("gid change: tid=%d pid=%d from %d to %d\n",
                        nlcn_msg.proc_ev.event_data.id.process_pid,
                        nlcn_msg.proc_ev.event_data.id.process_tgid,
                        nlcn_msg.proc_ev.event_data.id.r.rgid,
                        nlcn_msg.proc_ev.event_data.id.e.egid);
                break;
            case PROC_EVENT_EXIT:
                printf("exit: tid=%d pid=%d exit_code=%d\n",
                        nlcn_msg.proc_ev.event_data.exit.process_pid,
                        nlcn_msg.proc_ev.event_data.exit.process_tgid,
                        nlcn_msg.proc_ev.event_data.exit.exit_code);
                break;
            default:
                printf("unhandled proc event\n");
                break;
        }
    }

    return 0;
}

static void on_sigint(__attribute__ ((unused)) int unused)
{
    need_exit = true;
}

int main()
{
    int nl_sock;
    int rc = EXIT_SUCCESS;

    signal(SIGINT, &on_sigint);
    siginterrupt(SIGINT, true);
    nl_sock = nl_connect();
    if (nl_sock == -1)
        exit(EXIT_FAILURE);
    rc = set_proc_ev_listen(nl_sock, true);
    if (rc == -1) {
        rc = EXIT_FAILURE;
        goto out;
    }
    rc = handle_proc_ev(nl_sock);
    if (rc == -1) {
        rc = EXIT_FAILURE;
        goto out;
    }
    set_proc_ev_listen(nl_sock, false);
out:
    close(nl_sock);
    exit(rc);
}

Восходящий поток GitHub ,код адаптирован из:https://bewareofgeek.livejournal.com/2945.html

Однако я не думаю, что вы можете получить данные процесса, такие как UID и аргументы процесса, потому что exec_proc_eventсодержит так мало данных:https://github.com/torvalds/linux/blob/v4.16/include/uapi/linux/cn_proc.h#L80Мы могли бы попытаться сразу прочитать их из /proc, но есть риск что процесс завершился, а другой взял его PID, поэтому он не будет надежным.

Протестировано на Ubuntu 17.10, в которой CONFIG_PROC_EVENTS=yвключен по умолчанию.

4
27.01.2020, 19:38

Вы можете использовать forkstat, как указано здесь:https://stackoverflow.com/a/40532202/781153

Установить с помощью:apt-get install forkstat

И просто беги:forkstat

4
27.01.2020, 19:38

TL;DR:использовать execnsoop.


  • Убедитесь, что KPROBES включены в ядре

    $ zgrep CONFIG_KPROBES= /boot/config-$(uname -r) /proc/config* 2> /dev/null
    /boot/config-4.15.0-64-generic:CONFIG_KPROBES=y
    
  • Установить Коллекция компилятора BPF (BCC)

    • Для Debian/Ubuntu также необходим пакет linux-headers-*:

      sudo apt-get install bpfcc-tools linux-headers-$(uname -r)
      
    • Для других дистрибутивов см. Установка BCC

  • Запустить execsnoop(примеры и параметры)

    root@ubuntu ~ # execsnoop-bpfcc -tx
    TIME(s) PCOMM            PID    PPID   RET ARGS
    5.773   ping             13027  12847    0 /bin/ping hostname
    
1
23.08.2020, 10:16

Несколько примеров использованияbpftraceдля достижения цели.

  1. Самый простой — отследить все execзвонки в системе:

    sudo bpftrace -e 'tracepoint:syscalls:sys_enter_exec*{ printf("pid: %d, comm: %s, args: ", pid, comm); join(args->argv); }'
    

    Необходимо следить как минимум за двумя точками трассировки sys_enter_execveи enter_execveat. В примере я использую символ *для соответствия обоим системным вызовам(этот синтаксис работает с 2019 года).

  2. Также может потребоваться отслеживать все потоки, создаваемые в системе, как:

    sudo bpftrace -e 'kprobe:_do_fork{ printf("pid = %d, comm = %s\n", pid, comm); }'
    

    Никаких аргументов процесса для вас в этом случае нет, тем не менее, это может быть полезно.

Чтобы увидеть список всех доступных событий, выполните bpftrace -l.

6
28.08.2020, 14:28

Для этого можно использовать несколько API-интерфейсов Linux, а также несколько инструментов пользовательского режима, использующих различные API-интерфейсы. Вот некоторые из API:

  • Соединитель процесса Netlink -это API, который делает именно то, что вам нужно, но есть проблемы с отслеживанием подробной информации о коротких -живых процессах
  • API аудита -API ядра, включенный по умолчанию в большинстве дистрибутивов, который может отправлять события в пользовательский режим для каждого системного вызова (если вы идете по этому пути, вам нужно отслеживать exec -как и fork -как системные вызовы)
  • tracepoints и kprobes -два API отладки ядра, которые можно использовать для получения информации о событиях жизненного цикла процесса
  • Решения на основе ebpf -можно использовать вместе с tracepoints/kprobes для фильтрации -событий в ядре или запуска различной логики
  • решения на основе ptrace -они включают простую отладку ptrace, а также API seccomp

На самом деле слишком много деталей, чтобы правильно сравнивать эти варианты в одном ответе StackOverflow, но я подробно писал об этом в другом месте.

3
11.10.2020, 11:27

Теги

Похожие вопросы