লিনাক্সে নতুন নির্মিত প্রসেসগুলি কীভাবে ট্র্যাক করবেন?


31

আমি জানি যে psএটির সাহায্যে সিস্টেমে চলমান প্রক্রিয়াগুলির তালিকা বা গাছটি দেখতে পাচ্ছি। তবে আমি যা অর্জন করতে চাই তা হ'ল কম্পিউটার ব্যবহার করার সময় তৈরি হওয়া নতুন প্রক্রিয়াগুলি "অনুসরণ" করা।

সাদৃশ্য হিসাবে, আপনি যখন tail -fকোনও ফাইল বা কোনও ইনপুটগুলিতে সংযুক্ত নতুন সামগ্রীগুলি অনুসরণ করতে ব্যবহার করেন, তখন আমি বর্তমানে তৈরি হওয়া প্রক্রিয়াটির একটি অনুসরণের তালিকা রাখতে চাই।

এটি কি সুস্পষ্ট?

উত্তর:


28

যদি kprobes কার্নেলে সক্ষম করা থাকে তবে আপনি পারফ-সরঞ্জামগুলিexecsnoop থেকে ব্যবহার করতে পারেন :

প্রথম টার্মিনালে:

% 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
X84_64- তে নতুন কার্নেল সংস্করণগুলির জন্য (> = 4.17 যদি আমি সঠিকভাবে বুঝতে পারি), গ্রেগের পারফ-সরঞ্জামগুলি আর কাজ করে না - তারা চালায় তবে কোনও অব্যবহৃত কল হিসাবে চালিত হওয়ার মতো কোনও প্রতিবেদন নেই। অন্য কোথাও গ্রেগের মন্তব্য অনুসারে, কার্নেলগুলি> = 4.7 এর সঠিক সমাধানটি এখানে উপলব্ধ বিপিএফ সংকলক সংগ্রহের বিপিএফ বাস্তবায়নটি ব্যবহার করুন: github.com/iovisor/bcc#tools এবং উবুন্টু এবং আধুনিক লিনাক্স হিসাবে bpfcc-tools
গাস

7

সবচেয়ে সহজ উপায় হ'ল সিস্টেম কল অডিটিং সক্ষম করা

বিস্তারিত জানার জন্য নীচের লিঙ্কটি দেখুন ,

রুট প্রসেস স্প্যান নিরীক্ষণের একটি সহজ উপায় কি কেউ জানেন? সার্ভার ফল্ট

আপনি যদি সমস্ত প্রক্রিয়া পর্যবেক্ষণ করেন তবে কেবলমাত্র -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);
}

গিটহাব আপসট্রিম , কোডটি এ থেকে অভিযোজিত: https://bewareofgeek.livejorter.com/2945.html

তবে আমি মনে করি না যে আপনি ইউআইডি এবং প্রক্রিয়া যুক্তিগুলির মতো প্রক্রিয়া ডেটা পেতে পারেন কারণ exec_proc_eventখুব অল্প ডেটা রয়েছে: https://github.com/torvalds/linux/blob/v4.16/incolve/uapi/linux/cn_proc .h # L80 আমরা এটি থেকে তাত্ক্ষণিকভাবে পড়ার চেষ্টা করতে পারি /proc, তবে ঝুঁকি রয়েছে যে প্রক্রিয়াটি শেষ হয়ে গেছে এবং অন্য একটি তার পিআইডি নিয়েছে, সুতরাং এটি নির্ভরযোগ্য হবে না।

উবুন্টু 17.10 এ পরীক্ষা করা হয়েছে, যা CONFIG_PROC_EVENTS=yডিফল্টরূপে সক্ষম হয়েছে।


2

আপনি দৃশ্যত ব্যবহার করে একটি প্রক্রিয়া অনুসরণ করতে পারেন strace। আপনি যদি প্রক্রিয়াটির পিআইডি জানেন তবে আপনি এটি করতে পারেন:

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

-fসুইচটি লক্ষ্য করুন । এটি আপনাকে নতুন তৈরি করা প্রক্রিয়াগুলি অনুসরণ করতে সহায়তা করবে যা প্রক্রিয়াটির বংশধর যাঁর উপরের কমান্ডে পিআইডি ব্যবহার করা হয়েছিল। স্ট্রেসের উপর তথ্যের জন্য এই প্রশ্নটি দেখুন।


স্পষ্টতই আপনি পিআইডি = 1 দিয়ে init প্রক্রিয়াটি সংযুক্ত করার অর্থ দিয়েছিলেন? দুর্ভাগ্যক্রমে এটি কাজ করে না, আমি আউটপুটে নতুন প্রসেসগুলির কোনও সৃষ্টি দেখতে পাচ্ছি না, এবং নতুন প্রসেসের জন্য বর্তমান পিড কয়েকশো পেরিয়ে গেছে এমন সময় লাইনের সংখ্যা কয়েক ডজন রয়েছে।
হাই-অ্যাঞ্জেল

0

আপনি forkstatএখানে বর্ণিত হিসাবে ব্যবহার করতে পারেন : https://stackoverflow.com/a/40532202/781153

এর সাথে ইনস্টল করুন: apt-get install forkstat

এবং কেবল চালান: forkstat

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.