it-swarm.com.de

Wie kann ich alle Prozessstarts unter Linux protokollieren?

Ich möchte ein Protokoll aller Prozesse erhalten, die mit dem Zeitpunkt des Starts und den Argumenten gestartet wurden, mit denen sie gestartet wurden. Ist das unter Linux möglich?

54
Brandon DuRette

Ihr Ausgangspunkt sollte auditiert werden.

Versuchen Sie so etwas:

apt-get install auditd
auditctl -a task,always
ausearch -i -sc execve
42
Mikel

Ich musste dies tun, außer (1) ich brauchte keine Zeit und (2) ich interessierte mich nur für Prozesse, die von einem bestimmten Prozess gestartet werden, und seine Kinder und nachfolgenden Nachkommen. Außerdem war es in der von mir verwendeten Umgebung nicht möglich, auditd oder accton abzurufen, aber es gab valgrind.

Stellen Sie dem gewünschten Prozess in der Befehlszeile Folgendes voran:

valgrind --trace-children=yes

Die Informationen, die Sie benötigen, werden in der Protokollausgabe von STDERR angezeigt.

8
Evgeni Sergeev

Sie könnten snoopy dafür verwenden.

Es ist sehr einfach zu installieren und kann seit 2.x beliebige Daten (Argumente, Umgebungsvariablen, cwd usw.) protokollieren.

Offenlegung: Snoopy Betreuer hier.

6
Bostjan Skufca

Sie können startmon ausführen und die Standardausgabe, Strg-C, befolgen, wenn Sie fertig sind. So kompilieren Sie startmon und führen es auf neueren von Red Hat abgeleiteten Distributionen (RHEL, Fedora, CentOS) aus:

Sudo yum install git cmake gcc-c++
git clone https://github.com/pturmel/startmon
cd startmon
cmake .
make
Sudo ./startmon -e

Unter Debian (und Ubuntu usw.) ändert sich die erste Zeile der obigen Änderungen in:

Sudo apt-get install git cmake g++

Alternativ können Sie das execsnoop-Skript in perf-tools ausprobieren, siehe diese Antwort . Standardmäßig werden nur die ersten 8 Argumente angezeigt (9 einschließlich des Programmnamens). Sie können dies über erhöhen

Sudo ./execsnoop -a 16

Wenn Sie keinen Root-Zugriff auf das System haben, können Sie am besten /proc weiter abfragen und hoffen, dass dieser alles abfängt (was nicht der Fall ist). Entfernen, um die Ausgabe zu vereinfachen) - Dies ist zwar nicht so gut wie das ordnungsgemäße Verfolgen mit einer der oben genannten Methoden, hat jedoch den leichten Vorteil, dass Trennzeichen zwischen den Befehlszeilenargumenten eindeutig angezeigt werden, falls Sie dies jemals mitteilen müssen Der Unterschied zwischen Leerzeichen innerhalb eines Arguments und Leerzeichen zwischen Argumenten. Dieses Skript ist ineffizient, da es die CPU (also einen seiner Kerne) zu 100% auslastet.

function pstail () { python -c 'import os
last=set(os.listdir("/proc")) ; o=x=""
while True:
 pids=set(os.listdir("/proc"))
 new=pids.difference(last);last=pids
 for n in new:
  try: o,x=x,[j for j in open("/proc/"+n+"/cmdline")
    .read().split(chr(0)) if j]
  except IOError: pass
  if x and not o==x: print n,x' ; }

pstail

Sie können auch execsnoop patchen, um genauer zu erfahren, welches Argument welches ist: grep -v sub.*arg < execsnoop > n && chmod +x n && mv n execsnoop

2
Silas S. Brown

CONFIG_FTRACE UND CONFIG_KPROBES BIS brendangregg/perf-tools

git clone https://github.com/brendangregg/perf-tools.git
cd perf-tools
git checkout 98d42a2a1493d2d1c651a5c396e015d4f082eb20
Sudo ./execsnoop

Auf einer anderen Shell:

while true; do sleep 1; date; done

Erste Shell zeigt Daten des Formats:

Tracing exec()s. Ctrl-C to end.                                                        
Instrumenting sys_execve                                                               
   PID   PPID ARGS 
 20109   4336 date                                                                                       
 20110   4336 sleep 1                                                                                    
 20111   4336 date                                                                                                                                                                                                 
 20112   4336 sleep 1                                                                                    
 20113   4336 date                                                                                       
 20114   4336 sleep 1                                                                                    
 20115   4336 date                                                                                       
 20116   4336 sleep 1

CONFIG_PROC_EVENTS

Beispielsitzung:

$ su
# ./proc_events &
# /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 macht die Ereignisse über einen Netlink-Socket für das Benutzerland verfügbar.

proc_events.c angepasst von: https://bewareofgeek.livejournal.com/2945.html

#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-Upsatream .

Ich glaube jedoch nicht, dass Sie Prozessdaten wie UID und Prozessargumente erhalten können, da exec_proc_event so wenig Daten enthält: https://github.com/torvalds/linux/blob/v4 .16/include/uapi/linux/cn_proc.h # L80 Wir könnten versuchen, es sofort aus /proc zu lesen, aber es besteht die Gefahr, dass der Prozess beendet wird und ein anderer seine PID erhält es wäre nicht zuverlässig.

Getestet in Ubuntu 17.10.

Sie können auch über verwenden, um die Ressourcennutzung nach Prozessen anzuzeigen. Dies ist ein nützliches Tool zum Protokollieren und Analysieren der Ressourcennutzung in jedem Teil der Zeit

0
Quarind