Wie kann ich alle Prozessstarts unter Linux protokollieren?

55

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?

Brandon DuRette
quelle

Antworten:

43

Ihr Ausgangspunkt sollte auditiert werden.

Versuchen Sie so etwas:

apt-get install auditd
auditctl -a task,always
ausearch -i -sc execve
Mikel
quelle
1
Ich erhalte eine Fehlermeldung. The audit system is disabledWo kann ich sie aktivieren?
Tombart
1
chmod 0750 /sbin/audispd
Nun,
ist , sagt Unable to set audit pid, exitingaber ich denke , dass das eigentliche Problem , dass das System läuft in LXC Containern sein wird
Tombart
Wie lässt sich Audit in systemd journald integrieren? Überlappen sich ihre Funktionen?
CMCDragonkai
Ich habe es auf einem Live-Server ausprobiert und habe es effektiv getötet. Ich reagierte fast nicht mehr. Ich habe es kaum geschafft, diese Regel zu entfernen und den Server wieder
reaktionsfähig zu
10

Ich musste dies tun, außer (1) ich brauchte nicht die Zeit und (2) ich interessierte mich nur für Prozesse, die von einem bestimmten Prozess gestartet werden, und seine Kinder und nachfolgenden Nachkommen. Auch in der Umgebung, die ich benutzte, war es nicht möglich, auditdoder zu bekommen accton, 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.

Evgeni Sergeev
quelle
3
Standardmäßig wird valgrind mit dem memcheckTool ausgeführt. Um das Werkzeug und den damit verbundenen Protokollierung zu deaktivieren, und drucken nur die Schaffung neuer Befehle (zusätzlich zu dem üblichen Ausgang Ihres Programms), verwenden Sie stattdessen den folgenden Befehl: valgrind --tool=none --trace-children=yes [command and args here]. Immer wenn ein Unterprozess erzeugt wird, protokolliert Valgrind den vollständigen Befehl, einschließlich der Argumente, die an ihn übergeben wurden.
Rob W
6

Sie könnten dafür snoopy verwenden .

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

Offenlegung: Snoopy Betreuer hier.

Bostjan Skufca
quelle
2

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 execsnoopSkript 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 weiter abfragen /procund hoffen, dass es alles abfängt (was nicht der Vollständigkeit halber) 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 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 patchen execsnoop, um genauer zu sagen, welches Argument welches ist:grep -v sub.*arg < execsnoop > n && chmod +x n && mv n execsnoop

Silas S. Brown
quelle
1

CONFIG_FTRACEund CONFIG_KPROBESdurchbrendangregg/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_EVENTSLegt die Ereignisse über einen Netlink-Socket für das Benutzerland offen .

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 abrufen können, da diese exec_proc_eventso wenig Daten enthalten: https://github.com/torvalds/linux/blob/v4.16/include/uapi/linux/cn_proc .h # L80 Wir könnten versuchen, es sofort zu lesen /proc, aber es besteht die Gefahr, dass der Prozess beendet wird und ein anderer seine PID erhält, so dass es nicht zuverlässig ist.

Getestet in Ubuntu 17.10.

Ciro Santilli ist ein Schauspieler
quelle
0

Sie können atop auch zum Anzeigen der Ressourcennutzung nach Prozessen verwenden. Dies ist ein nützliches Tool zum Protokollieren und Analysieren der Ressourcennutzung in jedem Teil der Zeit

Quarind
quelle
-3

Sie können versuchen, cat ~/.bash_history Es gibt system log viewer, das kann Ihnen helfen.

Kracekumar
quelle
1
~/.bash_historyenthält nur Befehle, die ich anscheinend in einem Terminal ausgeführt habe. Ich suche nach einem Protokoll aller ausgeführten Programme, z. B. wenn ich auf ein Symbol klicke, um meinen E-Mail-Client oder gedit zu öffnen, oder wenn ich meinen Browser öffne und mein Browser selbst einen anderen Prozess ausführt. Die Antwort von new123456 hat es geschafft.
Runeks
1
Fügen wir hinzu, dass der Befehl historydie übliche Art ist, auf diese Informationen zuzugreifen.
Bryn