लिनक्स में नव निर्मित प्रक्रियाओं को कैसे ट्रैक करें?


31

मुझे पता है कि psमैं सिस्टम में चल रही मौजूदा प्रक्रियाओं की सूची या पेड़ देख सकता हूं। लेकिन मैं जो हासिल करना चाहता हूं वह कंप्यूटर का उपयोग करते समय बनाई गई नई प्रक्रियाओं का "पालन" करना है।

सादृश्य के रूप में, जब आप tail -fकिसी फ़ाइल या किसी इनपुट पर संलग्न नई सामग्री का पालन करने के लिए उपयोग करते हैं , तो मैं उस प्रक्रिया का अनुसरण सूची रखना चाहता हूं जो वर्तमान में बनाई जा रही हैं।

क्या यह भी पॉसिबल है?

जवाबों:


28

यदि कर्नेल को कर्नेल में सक्षम किया जाता है तो आप perf-toolsexecsnoop से उपयोग कर सकते हैं :

पहले टर्मिनल में:

% 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...

2
नए कर्नेल संस्करणों के लिए (> = 4.17 यदि मैं सही तरीके से समझता हूं) तो x84_64 पर, ग्रेग के परफेक्ट-टूल्स अब काम नहीं करते हैं - वे चलते हैं लेकिन इसमें कोई रिपोर्ट नहीं है क्योंकि यह एक अप्रयुक्त कॉल को लिखता है। ग्रीग की टिप्पणियों के अनुसार, गुठली> = 4.7 के लिए सही समाधान, बीपीएफ कंपाइलर संग्रह में बीपीएफ कार्यान्वयन का उपयोग यहां उपलब्ध है: github.com/iovisor/bcc#tools और उबंटू और आधुनिक लाइनक्स के रूप में bpfcc-tools
Guss

7

सबसे आसान तरीका है सिस्टम कॉल ऑडिटिंग को सक्षम करना

विवरण के लिए निम्नलिखित लिंक देखें details

क्या किसी को रूट प्रोसेस स्पॉन की निगरानी करने का एक सरल तरीका पता है | सर्वर दोष

यदि आप सभी प्रक्रियाओं की निगरानी कर रहे हैं, तो -F uid=0भाग को हटा दें

लॉग को लिखा जाता है /var/log/audit/audit.log


उन 3 कड़ियों में से कोई भी मेरे सवाल का जवाब नहीं देता है। पहले दो इसे हल करने के लिए कुछ कोडिंग के बारे में हैं और आखिरी कोई भी जवाब नहीं देता है। मैं जो कुछ पूछ रहा हूं वह कुछ कमांड के बारे में है और कोड के कुछ टुकड़े को नहीं लिख रहा है
पाब्लो माटीस गोमेज़

@ पाब्लोमैटिसगोमेज़ ने अद्यतन किया
डेज़ी

3

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नेटलिंक सॉकेट के माध्यम से उपयोगकर्तालैंड में होने वाली घटनाओं को उजागर करता है ।

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

हालाँकि मुझे नहीं लगता कि आप यूआईडी जैसे प्रक्रिया डेटा प्राप्त कर सकते हैं और तर्क वितर्क कर सकते हैं क्योंकि exec_proc_eventइसमें बहुत कम डेटा है: https://github.com/torvalds/linux/blob/v4.16/include/uapi/linux-cn_proc .h # L80 हम इसे तुरंत पढ़ने की कोशिश कर सकते हैं /proc, लेकिन एक जोखिम है कि प्रक्रिया समाप्त हो गई और एक अन्य ने अपना पीआईडी ​​ले लिया, इसलिए यह विश्वसनीय नहीं होगा।

Ubuntu 17.10 पर परीक्षण किया गया है, जो CONFIG_PROC_EVENTS=yडिफ़ॉल्ट रूप से सक्षम है।


2

आप जाहिरा तौर पर कर सकते हैं का पालन करें का उपयोग कर एक प्रक्रिया strace। यदि आपको प्रक्रिया का पीआईडी ​​पता है तो आप कर सकते हैं:

strace -o strace-<pid>.out -f -p <pid>

-fस्विच को नोटिस करें। यह आपको नई बनाई गई प्रक्रियाओं का पालन करने में मदद करेगा, जो उस प्रक्रिया के वंशज हैं जिनका पीआईडी ​​कमांड में उपयोग किया गया था, ऊपर। स्ट्रेस की जानकारी के लिए यह प्रश्न देखें ।


जाहिर है कि आप init प्रक्रिया से जुड़ने के लिए थे, pid = 1 के साथ, सही है? दुर्भाग्य से यह काम नहीं करता है, मैं आउटपुट को नई प्रक्रियाओं के किसी भी निर्माण में नहीं देखता हूं, और नई प्रक्रियाओं के लिए मौजूदा पिड कुछ सैकड़ों के माध्यम से जाने पर लाइनों की संख्या कुछ दर्जनों है।
हाय-एंजेल

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.