Bagaimana saya bisa mencatat semua proses peluncuran di Linux?

55

Saya ingin mendapatkan log dari semua proses yang diluncurkan dengan waktu mereka diluncurkan dan argumen mereka diluncurkan. Apakah ini mungkin di Linux?

Brandon DuRette
sumber

Jawaban:

43

Titik awal Anda harus diaudit.

Coba sesuatu seperti ini:

apt-get install auditd
auditctl -a task,always
ausearch -i -sc execve
Mikel
sumber
1
Saya mendapatkan kesalahan The audit system is disabledDi mana saya bisa mengaktifkannya?
Tombart
1
baik satu masalah bisa diselesaikan dengan chmod 0750 /sbin/audispdtetapi masih tidak berfungsi (Debian Wheezy)
Tombart
dikatakan Unable to set audit pid, exitingtetapi saya kira masalah sebenarnya adalah bahwa sistem tersebut berjalan dalam wadah LXC
Tombart
Bagaimana audit terintegrasi dengan systemd journald? Apakah fungsinya tumpang tindih?
CMCDragonkai
Saya mencoba ini di server langsung dan saya secara efektif membunuhnya, menjadi hampir tidak responsif. Saya nyaris tidak berhasil menghapus aturan ini dan membuat server responsif lagi
Shocker
10

Saya perlu melakukan ini, kecuali (1) Saya tidak membutuhkan waktu dan (2) Saya hanya tertarik pada proses yang dimulai oleh proses tertentu, dan anak-anaknya serta keturunan selanjutnya. Juga, di lingkungan saya menggunakan, itu tidak mungkin untuk mendapatkan auditdatau accton, tapi ada valgrind.

Awali yang berikut ini ke proses yang menarik di baris perintah:

valgrind --trace-children=yes

Informasi yang Anda butuhkan ada di log output yang ditampilkan di STDERR.

Evgeni Sergeev
sumber
3
Secara default, valgrind bekerja dengan memcheckalat ini. Untuk menonaktifkan alat dan logging terkait, dan hanya mencetak penciptaan perintah baru (selain output biasa program anda), gunakan perintah berikut ini sebagai gantinya: valgrind --tool=none --trace-children=yes [command and args here]. Setiap kali subproses muncul, Valgrind kemudian akan mencatat perintah lengkap, termasuk argumen yang diteruskan ke sana.
Rob W
6

Anda bisa menggunakan snoopy untuk ini.

Sangat mudah untuk menginstal, dan karena 2.x dapat mencatat data sewenang-wenang (argumen, variabel lingkungan, cwd, dll.).

Pengungkapan: Snoopy maintainer di sini.

Bostjan Skufca
sumber
2

Anda dapat menjalankan startmon dan mengikuti output standarnya, Ctrl-C saat selesai. Berikut ini cara mengkompilasi dan menjalankan startmon pada distro yang diturunkan Red Hat baru-baru ini (RHEL, Fedora, CentOS):

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

Pada Debian (dan Ubuntu dll), baris pertama dari perubahan di atas menjadi:

sudo apt-get install git cmake g++

Atau Anda dapat mencoba execsnoopskrip di perf-tools, lihat jawaban ini . Secara default hanya 8 argumen pertama yang ditampilkan (9 termasuk nama program); Anda dapat meningkatkan ini melalui

sudo ./execsnoop -a 16

Jika Anda tidak memiliki akses root ke sistem, yang terbaik yang dapat Anda lakukan adalah tetap melakukan polling /procdan berharap itu menangkap segalanya (yang tidak akan terjadi), tetapi untuk kelengkapannya adalah skrip untuk melakukan itu (saya telah membuat duplikat-penghapusan untuk menyederhanakan output) - walaupun ini tidak sebagus melacak mereka dengan benar dengan salah satu metode di atas, itu memang memiliki sedikit keuntungan menampilkan pemisah antara argumen baris perintah, jika Anda perlu memberitahu perbedaan antara spasi di dalam argumen dan ruang antara argumen. Script ini tidak efisien karena menggunakan CPU (well, salah satu core-nya) 100% dari waktu.

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

Anda juga dapat menambal execsnoopuntuk memberi tahu Anda secara lebih eksplisit argumen mana yang:grep -v sub.*arg < execsnoop > n && chmod +x n && mv n execsnoop

Silas S. Brown
sumber
1

CONFIG_FTRACEdan CONFIG_KPROBESmelaluibrendangregg/perf-tools

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

Di shell lain:

while true; do sleep 1; date; done

Shell pertama menunjukkan data format:

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

Sesi sampel:

$ 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_EVENTSmengekspos peristiwa ke userland melalui soket netlink .

proc_events.c diadaptasi dari: 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 .

Namun saya tidak berpikir bahwa Anda dapat memperoleh data proses seperti UID dan memproses argumen karena exec_proc_eventmengandung data yang sangat sedikit: https://github.com/torvalds/linux/blob/v4.16/include/uapi/linux/cn_proc .h # L80 Kita dapat mencoba untuk segera membacanya /proc, tetapi ada risiko bahwa proses selesai dan yang lain mengambil PID-nya, sehingga tidak dapat diandalkan.

Diuji di Ubuntu 17.10.

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
sumber
0

Anda juga dapat menggunakan di atas untuk melihat penggunaan sumber daya dengan proses. Ini adalah alat yang berguna untuk mencatat dan menganalisis penggunaan sumber daya di setiap bagian waktu

Quarind
sumber
-3

Anda dapat mencoba cat ~/.bash_history Ada system log viewer, ini dapat membantu Anda keluar.

Kracekumar
sumber
1
~/.bash_historyhanya berisi perintah yang sudah saya jalankan di terminal, rupanya. Saya mencari log semua program yang dijalankan, misalnya ketika saya mengklik ikon untuk membuka klien email saya, gedit, atau saya membuka browser saya, dan browser saya menjalankan proses lain dengan sendirinya. jawaban new123456 berhasil.
runeks
1
Mari kita juga menambahkan bahwa perintah historyadalah cara biasa mengakses informasi ini.
bryn